mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-30 14:20:47 +00:00
Fix disappear after read
This commit is contained in:
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…
x
Reference in New Issue
Block a user