Fix disappear after read

pull/1313/head
Andrew 6 months ago
parent 6fbae28d70
commit 7b26de5bd6

@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.conversation.v2.messages
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
@ -22,6 +23,8 @@ import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class ControlMessageView : LinearLayout { class ControlMessageView : LinearLayout {
private val TAG = "ControlMessageView"
private lateinit var binding: ViewControlMessageBinding private lateinit var binding: ViewControlMessageBinding
constructor(context: Context) : super(context) { initialize() } constructor(context: Context) : super(context) { initialize() }
@ -47,6 +50,7 @@ class ControlMessageView : LinearLayout {
binding.apply { binding.apply {
expirationTimerView.isVisible = true expirationTimerView.isVisible = true
Log.d(TAG, "bind() called, messageBody = $messageBody")
expirationTimerView.setExpirationTime(message.expireStarted, message.expiresIn) expirationTimerView.setExpirationTime(message.expireStarted, message.expiresIn)

@ -1,3 +1,12 @@
package org.thoughtcrime.securesms.database package org.thoughtcrime.securesms.database
data class ExpirationInfo(val id: Long, val expiresIn: Long, val expireStarted: Long, val isMms: Boolean) data class ExpirationInfo(
val id: Long,
val timestamp: Long,
val expiresIn: Long,
val expireStarted: Long,
val isMms: Boolean
) {
private fun isDisappearAfterSend() = timestamp == expireStarted
fun isDisappearAfterRead() = expiresIn > 0 && !isDisappearAfterSend()
}

@ -305,6 +305,8 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
} }
override fun markExpireStarted(messageId: Long, startedTimestamp: Long) { override fun markExpireStarted(messageId: Long, startedTimestamp: Long) {
Log.d(TAG, "markExpireStarted() called with: messageId = $messageId, startedTimestamp = $startedTimestamp")
val contentValues = ContentValues() val contentValues = ContentValues()
contentValues.put(EXPIRE_STARTED, startedTimestamp) contentValues.put(EXPIRE_STARTED, startedTimestamp)
val db = databaseHelper.writableDatabase val db = databaseHelper.writableDatabase
@ -351,13 +353,14 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
) )
while (cursor != null && cursor.moveToNext()) { while (cursor != null && cursor.moveToNext()) {
if (MmsSmsColumns.Types.isSecureType(cursor.getLong(3))) { if (MmsSmsColumns.Types.isSecureType(cursor.getLong(3))) {
val syncMessageId = val timestamp = cursor.getLong(2)
SyncMessageId(fromSerialized(cursor.getString(1)), cursor.getLong(2)) val syncMessageId = SyncMessageId(fromSerialized(cursor.getString(1)), timestamp)
val expirationInfo = ExpirationInfo( val expirationInfo = ExpirationInfo(
cursor.getLong(0), id = cursor.getLong(0),
cursor.getLong(4), timestamp = timestamp,
cursor.getLong(5), expiresIn = cursor.getLong(4),
true expireStarted = cursor.getLong(5),
isMms = true
) )
result.add(MarkedMessageInfo(syncMessageId, expirationInfo)) result.add(MarkedMessageInfo(syncMessageId, expirationInfo))
} }

@ -363,8 +363,9 @@ public class SmsDatabase extends MessagingDatabase {
cursor = database.query(TABLE_NAME, new String[] {ID, ADDRESS, DATE_SENT, TYPE, EXPIRES_IN, EXPIRE_STARTED}, where, arguments, null, null, null); cursor = database.query(TABLE_NAME, new String[] {ID, ADDRESS, DATE_SENT, TYPE, EXPIRES_IN, EXPIRE_STARTED}, where, arguments, null, null, null);
while (cursor != null && cursor.moveToNext()) { while (cursor != null && cursor.moveToNext()) {
SyncMessageId syncMessageId = new SyncMessageId(Address.fromSerialized(cursor.getString(1)), cursor.getLong(2)); long timestamp = cursor.getLong(2);
ExpirationInfo expirationInfo = new ExpirationInfo(cursor.getLong(0), cursor.getLong(4), cursor.getLong(5), false); SyncMessageId syncMessageId = new SyncMessageId(Address.fromSerialized(cursor.getString(1)), timestamp);
ExpirationInfo expirationInfo = new ExpirationInfo(cursor.getLong(0), timestamp, cursor.getLong(4), cursor.getLong(5), false);
results.add(new MarkedMessageInfo(syncMessageId, expirationInfo)); results.add(new MarkedMessageInfo(syncMessageId, expirationInfo));
} }

@ -94,6 +94,8 @@ import org.thoughtcrime.securesms.util.SessionMetaProtocol
import java.security.MessageDigest import java.security.MessageDigest
import network.loki.messenger.libsession_util.util.Contact as LibSessionContact import network.loki.messenger.libsession_util.util.Contact as LibSessionContact
private const val TAG = "Storage"
open class Storage( open class Storage(
context: Context, context: Context,
helper: SQLCipherOpenHelper, helper: SQLCipherOpenHelper,
@ -240,6 +242,7 @@ open class Storage(
} }
override fun markConversationAsRead(threadId: Long, lastSeenTime: Long, force: Boolean) { override fun markConversationAsRead(threadId: Long, lastSeenTime: Long, force: Boolean) {
Log.d(TAG, "markConversationAsRead() called with: threadId = $threadId, lastSeenTime = $lastSeenTime, force = $force")
val threadDb = DatabaseComponent.get(context).threadDatabase() val threadDb = DatabaseComponent.get(context).threadDatabase()
getRecipientForThread(threadId)?.let { recipient -> getRecipientForThread(threadId)?.let { recipient ->
val currentLastRead = threadDb.getLastSeenAndHasSent(threadId).first() val currentLastRead = threadDb.getLastSeenAndHasSent(threadId).first()
@ -1722,6 +1725,8 @@ open class Storage(
} }
override fun setExpirationConfiguration(config: ExpirationConfiguration) { override fun setExpirationConfiguration(config: ExpirationConfiguration) {
Log.d(TAG, "setExpirationConfiguration() called with: config = $config")
val recipient = getRecipientForThread(config.threadId) ?: return val recipient = getRecipientForThread(config.threadId) ?: return
val expirationDb = DatabaseComponent.get(context).expirationConfigurationDatabase() val expirationDb = DatabaseComponent.get(context).expirationConfigurationDatabase()

@ -58,7 +58,7 @@ class MarkReadReceiver : BroadcastReceiver() {
) { ) {
if (markedReadMessages.isEmpty()) return if (markedReadMessages.isEmpty()) return
Log.d(TAG, "process() called with: context = $context, markedReadMessages = $markedReadMessages") Log.d(TAG, "process() called with: markedReadMessages = $markedReadMessages")
sendReadReceipts(context, markedReadMessages) sendReadReceipts(context, markedReadMessages)
@ -133,13 +133,16 @@ class MarkReadReceiver : BroadcastReceiver() {
expirationInfo: ExpirationInfo, expirationInfo: ExpirationInfo,
expiresIn: Long = expirationInfo.expiresIn expiresIn: Long = expirationInfo.expiresIn
) { ) {
Log.d(TAG, "scheduleDeletion() called with: context = $context, expirationInfo = $expirationInfo, expiresIn = $expiresIn") Log.d(TAG, "MarkReadReceiver#scheduleDeletion() called with: expirationInfo = $expirationInfo, expiresIn = $expiresIn")
if (expiresIn <= 0 || expirationInfo.expireStarted > 0) return val now = nowWithOffset
val now = SnodeAPI.nowWithOffset val expireStarted = expirationInfo.expireStarted
val db = DatabaseComponent.get(context!!).run { if (expirationInfo.isMms) mmsDatabase() else smsDatabase() }
db.markExpireStarted(expirationInfo.id, now) if (expirationInfo.isDisappearAfterRead() && expireStarted == 0L || now < expireStarted) {
val db = DatabaseComponent.get(context!!).run { if (expirationInfo.isMms) mmsDatabase() else smsDatabase() }
db.markExpireStarted(expirationInfo.id, now)
}
ApplicationContext.getInstance(context).expiringMessageManager.scheduleDeletion( ApplicationContext.getInstance(context).expiringMessageManager.scheduleDeletion(
expirationInfo.id, expirationInfo.id,

@ -13,7 +13,7 @@ import org.session.libsession.messaging.sending_receiving.attachments.Attachment
* *
* **Note:** `nil` if this isn't a sync message. * **Note:** `nil` if this isn't a sync message.
*/ */
class VisibleMessage( data class VisibleMessage(
var syncTarget: String? = null, var syncTarget: String? = null,
var text: String? = null, var text: String? = null,
val attachmentIDs: MutableList<Long> = mutableListOf(), val attachmentIDs: MutableList<Long> = mutableListOf(),

@ -68,7 +68,6 @@ fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content,
// Do nothing if the message was outdated // Do nothing if the message was outdated
if (MessageReceiver.messageIsOutdated(message, threadId, openGroupID)) { return } if (MessageReceiver.messageIsOutdated(message, threadId, openGroupID)) { return }
MessageReceiver.updateExpiryIfNeeded(message, proto, openGroupID)
when (message) { when (message) {
is ReadReceipt -> handleReadReceipt(message) is ReadReceipt -> handleReadReceipt(message)
is TypingIndicator -> handleTypingIndicator(message) is TypingIndicator -> handleTypingIndicator(message)
@ -154,7 +153,9 @@ fun MessageReceiver.cancelTypingIndicatorsIfNeeded(senderPublicKey: String) {
} }
private fun MessageReceiver.handleExpirationTimerUpdate(message: ExpirationTimerUpdate) { private fun MessageReceiver.handleExpirationTimerUpdate(message: ExpirationTimerUpdate) {
if (ExpirationConfiguration.isNewConfigEnabled) return SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message)
if (isNewConfigEnabled) return
val module = MessagingModuleConfiguration.shared val module = MessagingModuleConfiguration.shared
try { try {
@ -171,7 +172,6 @@ private fun MessageReceiver.handleExpirationTimerUpdate(message: ExpirationTimer
} catch (e: Exception) { } catch (e: Exception) {
Log.e("Loki", "Failed to update expiration configuration.") Log.e("Loki", "Failed to update expiration configuration.")
} }
SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message)
} }
private fun MessageReceiver.handleDataExtractionNotification(message: DataExtractionNotification) { private fun MessageReceiver.handleDataExtractionNotification(message: DataExtractionNotification) {
@ -269,58 +269,6 @@ fun handleMessageRequestResponse(message: MessageRequestResponse) {
} }
//endregion //endregion
fun MessageReceiver.updateExpiryIfNeeded(
message: Message,
proto: SignalServiceProtos.Content,
openGroupID: String?
) {
val storage = MessagingModuleConfiguration.shared.storage
val sentTime = message.sentTimestamp ?: throw MessageReceiver.Error.InvalidMessage
val threadID =
storage.getThreadIdFor(message.sender!!, message.groupPublicKey, openGroupID, false)
?: throw MessageReceiver.Error.NoThread
val recipient = storage.getRecipientForThread(threadID) ?: throw MessageReceiver.Error.NoThread
if (!recipient.isLocalNumber) {
val disappearingState = if (proto.hasExpirationType()) Recipient.DisappearingState.UPDATED else Recipient.DisappearingState.LEGACY
storage.updateDisappearingState(message.sender!!, threadID, disappearingState)
}
if (!proto.hasLastDisappearingMessageChangeTimestamp() && !isNewConfigEnabled) return
val localConfig = storage.getExpirationConfiguration(threadID)
val durationSeconds = if (proto.hasExpirationTimer()) proto.expirationTimer else 0
val type = if (proto.hasExpirationType()) proto.expirationType else null
val expiryMode = type?.expiryMode(durationSeconds.toLong()) ?: ExpiryMode.NONE
val lastDisappearingMessageChangeTimestamp = proto.lastDisappearingMessageChangeTimestamp
// don't update any values for open groups
if (recipient.isOpenGroupRecipient && type != null) throw MessageReceiver.Error.InvalidMessage
val incoming1on1 = recipient.isContactRecipient && !message.isSenderSelf
val remoteConfig = ExpirationConfiguration(
threadID,
expiryMode,
lastDisappearingMessageChangeTimestamp
)
remoteConfig.takeUnless { incoming1on1 }?.takeIf {
localConfig == null
|| it.updatedTimestampMs > localConfig.updatedTimestampMs
|| !isNewConfigEnabled && !proto.hasLastDisappearingMessageChangeTimestamp()
}?.let(storage::setExpirationConfiguration)
if (message is ExpirationTimerUpdate) {
SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message)
}
}
private fun SignalServiceProtos.Content.ExpirationType.expiryMode(durationSeconds: Long) = takeIf { durationSeconds > 0 }?.let { private fun SignalServiceProtos.Content.ExpirationType.expiryMode(durationSeconds: Long) = takeIf { durationSeconds > 0 }?.let {
when (it) { when (it) {
SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ -> ExpiryMode.AfterRead(durationSeconds) SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ -> ExpiryMode.AfterRead(durationSeconds)
@ -465,14 +413,10 @@ fun MessageReceiver.handleVisibleMessage(
// Persist the message // Persist the message
message.threadID = threadID message.threadID = threadID
val messageID = val messageID = storage.persist(message, quoteModel, linkPreviews, message.groupPublicKey, openGroupID, attachments, runThreadUpdate) ?: return null
storage.persist(message, quoteModel, linkPreviews, message.groupPublicKey, openGroupID, message.openGroupServerMessageID?.let {
attachments, runThreadUpdate val isSms = !message.isMediaMessage() && attachments.isEmpty()
) ?: return null storage.setOpenGroupServerMessageID(messageID, it, threadID, isSms)
val openGroupServerID = message.openGroupServerMessageID
if (openGroupServerID != null) {
val isSms = !(message.isMediaMessage() || attachments.isNotEmpty())
storage.setOpenGroupServerMessageID(messageID, openGroupServerID, threadID, isSms)
} }
return messageID return messageID
} }

@ -1,6 +1,7 @@
package org.session.libsession.messaging.utilities package org.session.libsession.messaging.utilities
import android.content.Context import android.content.Context
import android.util.Log
import org.session.libsession.R import org.session.libsession.R
import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.calls.CallMessageType import org.session.libsession.messaging.calls.CallMessageType
@ -17,6 +18,8 @@ import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.truncateIdForDisplay import org.session.libsession.utilities.truncateIdForDisplay
object UpdateMessageBuilder { object UpdateMessageBuilder {
private val TAG = "UpdateMessageBuilder"
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
private fun getSenderName(senderId: String) = storage.getContactWithSessionID(senderId) private fun getSenderName(senderId: String) = storage.getContactWithSessionID(senderId)
@ -85,6 +88,8 @@ object UpdateMessageBuilder {
timestamp: Long, timestamp: Long,
expireStarted: Long expireStarted: Long
): String { ): String {
Log.d(TAG, "buildExpirationTimerMessage() called with: duration = $duration, senderId = $senderId, isOutgoing = $isOutgoing, timestamp = $timestamp, expireStarted = $expireStarted")
if (!isOutgoing && senderId == null) return "" if (!isOutgoing && senderId == null) return ""
val senderName = if (isOutgoing) context.getString(R.string.MessageRecord_you) else getSenderName(senderId!!) val senderName = if (isOutgoing) context.getString(R.string.MessageRecord_you) else getSenderName(senderId!!)
return if (duration <= 0) { return if (duration <= 0) {
@ -98,6 +103,7 @@ object UpdateMessageBuilder {
} else { } else {
val time = ExpirationUtil.getExpirationDisplayValue(context, duration.toInt()) val time = ExpirationUtil.getExpirationDisplayValue(context, duration.toInt())
val action = context.getExpirationTypeDisplayValue(timestamp == expireStarted) val action = context.getExpirationTypeDisplayValue(timestamp == expireStarted)
Log.d(TAG, "action = $action because timestamp = $timestamp and expireStarted = $expireStarted equal = ${timestamp == expireStarted}")
if (isOutgoing) { if (isOutgoing) {
if (!isNewConfigEnabled) context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time) if (!isNewConfigEnabled) context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time)
else context.getString( else context.getString(
@ -114,7 +120,7 @@ object UpdateMessageBuilder {
action action
) )
} }
} }.also { Log.d(TAG, "display: $it") }
} }
fun buildDataExtractionMessage(context: Context, kind: DataExtractionNotificationInfoMessage.Kind, senderId: String? = null): String { fun buildDataExtractionMessage(context: Context, kind: DataExtractionNotificationInfoMessage.Kind, senderId: String? = null): String {

Loading…
Cancel
Save