mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 09:20:19 +01:00
Add support for admin delete.
This commit is contained in:
committed by
Cody Henthorne
parent
1968438ebb
commit
071fbfd916
@@ -188,7 +188,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
const val UNIDENTIFIED = "unidentified"
|
||||
const val REACTIONS_UNREAD = "reactions_unread"
|
||||
const val REACTIONS_LAST_SEEN = "reactions_last_seen"
|
||||
const val REMOTE_DELETED = "remote_deleted"
|
||||
const val SERVER_GUID = "server_guid"
|
||||
const val RECEIPT_TIMESTAMP = "receipt_timestamp"
|
||||
const val EXPORT_STATE = "export_state"
|
||||
@@ -223,6 +222,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
const val PINNED_UNTIL = "pinned_until"
|
||||
const val PINNING_MESSAGE_ID = "pinning_message_id"
|
||||
const val PINNED_AT = "pinned_at"
|
||||
const val DELETED_BY = "deleted_by"
|
||||
|
||||
const val QUOTE_NOT_PRESENT_ID = 0L
|
||||
const val QUOTE_TARGET_MISSING_ID = -1L
|
||||
@@ -273,7 +273,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
$VIEW_ONCE INTEGER DEFAULT 0,
|
||||
$REACTIONS_UNREAD INTEGER DEFAULT 0,
|
||||
$REACTIONS_LAST_SEEN INTEGER DEFAULT -1,
|
||||
$REMOTE_DELETED INTEGER DEFAULT 0,
|
||||
$MENTIONS_SELF INTEGER DEFAULT 0,
|
||||
$NOTIFIED_TIMESTAMP INTEGER DEFAULT 0,
|
||||
$SERVER_GUID TEXT DEFAULT NULL,
|
||||
@@ -292,7 +291,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
$VOTES_LAST_SEEN INTEGER DEFAULT 0,
|
||||
$PINNED_UNTIL INTEGER DEFAULT 0,
|
||||
$PINNING_MESSAGE_ID INTEGER DEFAULT 0,
|
||||
$PINNED_AT INTEGER DEFAULT 0
|
||||
$PINNED_AT INTEGER DEFAULT 0,
|
||||
$DELETED_BY INTEGER DEFAULT NULL REFERENCES ${RecipientTable.TABLE_NAME} (${RecipientTable.ID}) ON DELETE CASCADE
|
||||
)
|
||||
"""
|
||||
|
||||
@@ -325,7 +325,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
"CREATE INDEX IF NOT EXISTS $INDEX_THREAD_UNREAD_COUNT ON $TABLE_NAME ($THREAD_ID) WHERE $STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND $SCHEDULED_DATE = -1 AND $ORIGINAL_MESSAGE_ID IS NULL AND $READ = 0",
|
||||
"CREATE INDEX IF NOT EXISTS message_votes_unread_index ON $TABLE_NAME ($VOTES_UNREAD)",
|
||||
"CREATE INDEX IF NOT EXISTS message_pinned_until_index ON $TABLE_NAME ($PINNED_UNTIL)",
|
||||
"CREATE INDEX IF NOT EXISTS message_pinned_at_index ON $TABLE_NAME ($PINNED_AT)"
|
||||
"CREATE INDEX IF NOT EXISTS message_pinned_at_index ON $TABLE_NAME ($PINNED_AT)",
|
||||
"CREATE INDEX IF NOT EXISTS message_deleted_by_index ON $TABLE_NAME ($DELETED_BY)"
|
||||
)
|
||||
|
||||
private val MMS_PROJECTION_BASE = arrayOf(
|
||||
@@ -366,7 +367,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
VIEW_ONCE,
|
||||
REACTIONS_UNREAD,
|
||||
REACTIONS_LAST_SEEN,
|
||||
REMOTE_DELETED,
|
||||
MENTIONS_SELF,
|
||||
NOTIFIED_TIMESTAMP,
|
||||
VIEWED_COLUMN,
|
||||
@@ -381,7 +381,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
MESSAGE_EXTRAS,
|
||||
VOTES_UNREAD,
|
||||
VOTES_LAST_SEEN,
|
||||
PINNED_UNTIL
|
||||
PINNED_UNTIL,
|
||||
DELETED_BY
|
||||
)
|
||||
|
||||
private val MMS_PROJECTION: Array<String> = MMS_PROJECTION_BASE + "NULL AS ${AttachmentTable.ATTACHMENT_JSON_ALIAS}"
|
||||
@@ -427,7 +428,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
) AS ${AttachmentTable.ATTACHMENT_JSON_ALIAS}
|
||||
""".toSingleLine()
|
||||
|
||||
private const val IS_STORY_CLAUSE = "$STORY_TYPE > 0 AND $REMOTE_DELETED = 0"
|
||||
private const val IS_STORY_CLAUSE = "$STORY_TYPE > 0 AND $DELETED_BY IS NULL"
|
||||
private const val RAW_ID_WHERE = "$TABLE_NAME.$ID = ?"
|
||||
|
||||
private val SNIPPET_QUERY =
|
||||
@@ -1600,7 +1601,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
JOIN ${ThreadTable.TABLE_NAME} ON $TABLE_NAME.$THREAD_ID = ${ThreadTable.TABLE_NAME}.${ThreadTable.ID}
|
||||
WHERE
|
||||
$STORY_TYPE > 0 AND
|
||||
$REMOTE_DELETED = 0
|
||||
$DELETED_BY IS NULL
|
||||
${if (isOutgoingOnly) " AND is_outgoing != 0" else ""}
|
||||
ORDER BY
|
||||
is_unread DESC,
|
||||
@@ -2218,12 +2219,12 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
AppDependencies.databaseObserver.notifyConversationListListeners()
|
||||
}
|
||||
|
||||
fun markAsRemoteDelete(targetMessage: MessageRecord) {
|
||||
fun markAsRemoteDelete(targetMessage: MessageRecord, deletedBy: RecipientId) {
|
||||
writableDatabase.withinTransaction { db ->
|
||||
val hasRevision = (targetMessage as? MmsMessageRecord)?.latestRevisionId?.id != null
|
||||
if (hasRevision || targetMessage.isEditMessage) {
|
||||
val latestRevisionId = (targetMessage as? MmsMessageRecord)?.latestRevisionId?.id ?: targetMessage.id
|
||||
markAsRemoteDeleteInternal(latestRevisionId)
|
||||
markAsRemoteDeleteInternal(latestRevisionId, deletedBy)
|
||||
getPreviousEditIds(latestRevisionId).map { id ->
|
||||
db.update(TABLE_NAME)
|
||||
.values(
|
||||
@@ -2235,22 +2236,22 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
deleteMessage(id)
|
||||
}
|
||||
} else {
|
||||
markAsRemoteDeleteInternal(targetMessage.id)
|
||||
markAsRemoteDeleteInternal(targetMessage.id, deletedBy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun markAsRemoteDelete(messageId: Long) {
|
||||
fun markAsDeleteBySelf(messageId: Long) {
|
||||
val targetMessage: MessageRecord = getMessageRecord(messageId)
|
||||
markAsRemoteDelete(targetMessage)
|
||||
markAsRemoteDelete(targetMessage, Recipient.self().id)
|
||||
}
|
||||
|
||||
private fun markAsRemoteDeleteInternal(messageId: Long) {
|
||||
private fun markAsRemoteDeleteInternal(messageId: Long, deletedBy: RecipientId) {
|
||||
var deletedAttachments = false
|
||||
writableDatabase.withinTransaction { db ->
|
||||
db.update(TABLE_NAME)
|
||||
.values(
|
||||
REMOTE_DELETED to 1,
|
||||
DELETED_BY to deletedBy.toLong(),
|
||||
BODY to null,
|
||||
QUOTE_BODY to null,
|
||||
QUOTE_AUTHOR to null,
|
||||
@@ -4012,7 +4013,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
}
|
||||
|
||||
fun deleteRemotelyDeletedStory(messageId: Long) {
|
||||
if (readableDatabase.exists(TABLE_NAME).where("$ID = ? AND $REMOTE_DELETED = ?", messageId, 1).run()) {
|
||||
if (readableDatabase.exists(TABLE_NAME).where("$ID = ? AND $DELETED_BY > 0", messageId).run()) {
|
||||
deleteMessage(messageId)
|
||||
} else {
|
||||
Log.i(TAG, "Unable to delete remotely deleted story: $messageId")
|
||||
@@ -4595,7 +4596,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
val targetMessageDateReceived: Long = readableDatabase
|
||||
.select(DATE_RECEIVED, LATEST_REVISION_ID)
|
||||
.from(TABLE_NAME)
|
||||
.where("$DATE_SENT = $quoteId AND $FROM_RECIPIENT_ID = ? AND $REMOTE_DELETED = 0 AND $SCHEDULED_DATE = -1", authorId)
|
||||
.where("$DATE_SENT = $quoteId AND $FROM_RECIPIENT_ID = ? AND $DELETED_BY IS NULL AND $SCHEDULED_DATE = -1", authorId)
|
||||
.run()
|
||||
.readToSingleObject { cursor ->
|
||||
val latestRevisionId = cursor.requireLongOrNull(LATEST_REVISION_ID)
|
||||
@@ -4626,7 +4627,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
fun getMessagePositionInConversation(threadId: Long, receivedTimestamp: Long, authorId: RecipientId): Int {
|
||||
val validMessageExists: Boolean = readableDatabase
|
||||
.exists(TABLE_NAME)
|
||||
.where("$DATE_RECEIVED = $receivedTimestamp AND $FROM_RECIPIENT_ID = ? AND $REMOTE_DELETED = 0 AND $SCHEDULED_DATE = -1 AND $LATEST_REVISION_ID IS NULL", authorId)
|
||||
.where("$DATE_RECEIVED = $receivedTimestamp AND $FROM_RECIPIENT_ID = ? AND $DELETED_BY IS NULL AND $SCHEDULED_DATE = -1 AND $LATEST_REVISION_ID IS NULL", authorId)
|
||||
.run()
|
||||
|
||||
if (!validMessageExists) {
|
||||
@@ -5455,7 +5456,13 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
.where("$QUOTE_AUTHOR = ?", fromId)
|
||||
.run()
|
||||
|
||||
Log.d(TAG, "Remapped $fromId to $toId. fromRecipient: $fromCount, toRecipient: $toCount, quoteAuthor: $quoteAuthorCount")
|
||||
val deletedByCount = writableDatabase
|
||||
.update(TABLE_NAME)
|
||||
.values(DELETED_BY to toId.serialize())
|
||||
.where("$DELETED_BY = ?", fromId)
|
||||
.run()
|
||||
|
||||
Log.d(TAG, "Remapped $fromId to $toId. fromRecipient: $fromCount, toRecipient: $toCount, quoteAuthor: $quoteAuthorCount, deletedBy: $deletedByCount")
|
||||
}
|
||||
|
||||
override fun remapThread(fromId: Long, toId: Long) {
|
||||
@@ -6255,7 +6262,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
val expireTimerVersion = cursor.requireInt(EXPIRE_TIMER_VERSION)
|
||||
val unidentified = cursor.requireBoolean(UNIDENTIFIED)
|
||||
val isViewOnce = cursor.requireBoolean(VIEW_ONCE)
|
||||
val remoteDelete = cursor.requireBoolean(REMOTE_DELETED)
|
||||
val mentionsSelf = cursor.requireBoolean(MENTIONS_SELF)
|
||||
val notifiedTimestamp = cursor.requireLong(NOTIFIED_TIMESTAMP)
|
||||
var isViewed = cursor.requireBoolean(VIEWED_COLUMN)
|
||||
@@ -6269,6 +6275,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
val editCount = cursor.requireInt(REVISION_NUMBER)
|
||||
val isRead = cursor.requireBoolean(READ)
|
||||
val pinnedUntil = cursor.requireLong(PINNED_UNTIL)
|
||||
val deletedBy = cursor.requireLongOrNull(DELETED_BY)?.let { RecipientId.from(it) }
|
||||
val messageExtraBytes = cursor.requireBlob(MESSAGE_EXTRAS)
|
||||
val messageExtras = messageExtraBytes?.let { MessageExtras.ADAPTER.decode(it) }
|
||||
|
||||
@@ -6346,7 +6353,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
previews,
|
||||
unidentified,
|
||||
emptyList(),
|
||||
remoteDelete,
|
||||
mentionsSelf,
|
||||
notifiedTimestamp,
|
||||
isViewed,
|
||||
@@ -6364,6 +6370,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
editCount,
|
||||
isRead,
|
||||
pinnedUntil,
|
||||
deletedBy,
|
||||
messageExtras
|
||||
)
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
|
||||
AND $MESSAGE_ID IN (
|
||||
SELECT ${MessageTable.ID}
|
||||
FROM ${MessageTable.TABLE_NAME}
|
||||
WHERE ${MessageTable.REMOTE_DELETED} = 0
|
||||
WHERE ${MessageTable.DELETED_BY} IS NULL
|
||||
)
|
||||
)
|
||||
"""
|
||||
@@ -232,7 +232,7 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
|
||||
.where(
|
||||
"""
|
||||
$SENT_TIMESTAMP = ? AND
|
||||
(SELECT ${MessageTable.REMOTE_DELETED} FROM ${MessageTable.TABLE_NAME} WHERE ${MessageTable.ID} = $MESSAGE_ID) = 0
|
||||
(SELECT ${MessageTable.DELETED_BY} FROM ${MessageTable.TABLE_NAME} WHERE ${MessageTable.ID} = $MESSAGE_ID) IS NULL
|
||||
""",
|
||||
sentTimestamp
|
||||
)
|
||||
@@ -330,7 +330,7 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
|
||||
|
||||
val messagesWithoutAnyReceivers = localRows.map { it.messageId }.distinct() - remoteRows.map { it.messageId }.distinct()
|
||||
messagesWithoutAnyReceivers.forEach {
|
||||
SignalDatabase.messages.markAsRemoteDelete(it)
|
||||
SignalDatabase.messages.markAsDeleteBySelf(it)
|
||||
SignalDatabase.messages.deleteRemotelyDeletedStory(it)
|
||||
}
|
||||
}
|
||||
@@ -344,7 +344,7 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
|
||||
$TABLE_NAME.$RECIPIENT_ID,
|
||||
$ALLOWS_REPLIES,
|
||||
$DISTRIBUTION_ID,
|
||||
${MessageTable.REMOTE_DELETED}
|
||||
${MessageTable.DELETED_BY}
|
||||
FROM $TABLE_NAME
|
||||
INNER JOIN ${MessageTable.TABLE_NAME} ON ${MessageTable.TABLE_NAME}.${MessageTable.ID} = $TABLE_NAME.$MESSAGE_ID
|
||||
WHERE $TABLE_NAME.$SENT_TIMESTAMP = ?
|
||||
@@ -353,7 +353,7 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
|
||||
).use { cursor ->
|
||||
val results: MutableMap<RecipientId, SentStorySyncManifest.Entry> = mutableMapOf()
|
||||
while (cursor.moveToNext()) {
|
||||
val isRemoteDeleted = CursorUtil.requireBoolean(cursor, MessageTable.REMOTE_DELETED)
|
||||
val isRemoteDeleted = !CursorUtil.isNull(cursor, MessageTable.DELETED_BY)
|
||||
val recipientId = RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID))
|
||||
val distributionId = DistributionId.from(CursorUtil.requireString(cursor, DISTRIBUTION_ID))
|
||||
val distributionIdList: List<DistributionId> = if (isRemoteDeleted) emptyList() else listOf(distributionId)
|
||||
|
||||
@@ -2094,7 +2094,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
val extras: Extra? = if (record.isScheduled()) {
|
||||
Extra.forScheduledMessage(authorId)
|
||||
} else if (record.isRemoteDelete) {
|
||||
Extra.forRemoteDelete(authorId)
|
||||
Extra.forRemoteDelete(authorId, record.deletedBy!!)
|
||||
} else if (record.isViewOnce) {
|
||||
Extra.forViewOnce(authorId)
|
||||
} else if (record.isMms && (record as MmsMessageRecord).slideDeck.stickerSlide != null) {
|
||||
@@ -2280,7 +2280,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
isSticker = jsonObject.getBoolean("isSticker"),
|
||||
stickerEmoji = jsonObject.getString("stickerEmoji"),
|
||||
isAlbum = jsonObject.getBoolean("isAlbum"),
|
||||
isRemoteDelete = jsonObject.getBoolean("isRemoteDelete"),
|
||||
deletedBy = jsonObject.getString("deletedBy"),
|
||||
isMessageRequestAccepted = jsonObject.getBoolean("isMessageRequestAccepted"),
|
||||
isGv2Invite = jsonObject.getBoolean("isGv2Invite"),
|
||||
groupAddedBy = jsonObject.getString("groupAddedBy"),
|
||||
@@ -2353,8 +2353,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
@param:JsonProperty("isAlbum")
|
||||
val isAlbum: Boolean = false,
|
||||
@field:JsonProperty
|
||||
@param:JsonProperty("isRemoteDelete")
|
||||
val isRemoteDelete: Boolean = false,
|
||||
@param:JsonProperty("deletedBy")
|
||||
val deletedBy: String? = null,
|
||||
@field:JsonProperty
|
||||
@param:JsonProperty("isMessageRequestAccepted")
|
||||
val isMessageRequestAccepted: Boolean = true,
|
||||
@@ -2398,8 +2398,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
return Extra(isAlbum = true, individualRecipientId = individualRecipient.serialize())
|
||||
}
|
||||
|
||||
fun forRemoteDelete(individualRecipient: RecipientId): Extra {
|
||||
return Extra(isRemoteDelete = true, individualRecipientId = individualRecipient.serialize())
|
||||
fun forRemoteDelete(individualRecipient: RecipientId, deletedBy: RecipientId): Extra {
|
||||
return Extra(deletedBy = deletedBy.serialize(), individualRecipientId = individualRecipient.serialize())
|
||||
}
|
||||
|
||||
fun forMessageRequest(individualRecipient: RecipientId, isHidden: Boolean = false): Extra {
|
||||
|
||||
@@ -155,6 +155,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V298_DoNotBackupRel
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V299_AddAttachmentMetadataTable
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V300_AddKeyTransparencyColumn
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V301_RemoveCallLinkEpoch
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V302_AddDeletedByColumn
|
||||
import org.thoughtcrime.securesms.database.SQLiteDatabase as SignalSqliteDatabase
|
||||
|
||||
/**
|
||||
@@ -316,10 +317,11 @@ object SignalDatabaseMigrations {
|
||||
298 to V298_DoNotBackupReleaseNotes,
|
||||
299 to V299_AddAttachmentMetadataTable,
|
||||
300 to V300_AddKeyTransparencyColumn,
|
||||
301 to V301_RemoveCallLinkEpoch
|
||||
301 to V301_RemoveCallLinkEpoch,
|
||||
302 to V302_AddDeletedByColumn
|
||||
)
|
||||
|
||||
const val DATABASE_VERSION = 301
|
||||
const val DATABASE_VERSION = 302
|
||||
|
||||
@JvmStatic
|
||||
fun migrate(context: Application, db: SignalSqliteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.thoughtcrime.securesms.database.helpers.migration
|
||||
|
||||
import android.app.Application
|
||||
import org.signal.core.util.Stopwatch
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.database.SQLiteDatabase
|
||||
|
||||
/**
|
||||
* Adds column to messages to track who has deleted a given message
|
||||
*/
|
||||
@Suppress("ClassName")
|
||||
object V302_AddDeletedByColumn : SignalDatabaseMigration {
|
||||
|
||||
private val TAG = Log.tag(V302_AddDeletedByColumn::class.java)
|
||||
|
||||
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
val stopwatch = Stopwatch("migration", decimalPlaces = 2)
|
||||
|
||||
db.execSQL("ALTER TABLE message ADD COLUMN deleted_by INTEGER DEFAULT NULL REFERENCES recipient (_id) ON DELETE CASCADE")
|
||||
stopwatch.split("add-column")
|
||||
|
||||
db.execSQL("UPDATE message SET deleted_by = from_recipient_id WHERE remote_deleted > 0")
|
||||
stopwatch.split("copy-data")
|
||||
|
||||
db.execSQL("ALTER TABLE message DROP COLUMN remote_deleted")
|
||||
stopwatch.split("drop-column")
|
||||
|
||||
db.execSQL("CREATE INDEX message_deleted_by_index ON message (deleted_by)")
|
||||
stopwatch.split("create-index")
|
||||
|
||||
stopwatch.stop(TAG)
|
||||
}
|
||||
}
|
||||
@@ -53,13 +53,13 @@ public class InMemoryMessageRecord extends MessageRecord {
|
||||
false,
|
||||
false,
|
||||
Collections.emptyList(),
|
||||
false,
|
||||
0,
|
||||
false,
|
||||
-1,
|
||||
null,
|
||||
0,
|
||||
0,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,12 +108,12 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
private final boolean unidentified;
|
||||
private final List<ReactionRecord> reactions;
|
||||
private final long serverTimestamp;
|
||||
private final boolean remoteDelete;
|
||||
private final long notifiedTimestamp;
|
||||
private final long receiptTimestamp;
|
||||
private final MessageId originalMessageId;
|
||||
private final int revisionNumber;
|
||||
private final long pinnedUntil;
|
||||
private final RecipientId deletedBy;
|
||||
private final MessageExtras messageExtras;
|
||||
|
||||
protected Boolean isJumboji = null;
|
||||
@@ -130,13 +130,13 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
boolean hasReadReceipt,
|
||||
boolean unidentified,
|
||||
@NonNull List<ReactionRecord> reactions,
|
||||
boolean remoteDelete,
|
||||
long notifiedTimestamp,
|
||||
boolean viewed,
|
||||
long receiptTimestamp,
|
||||
@Nullable MessageId originalMessageId,
|
||||
int revisionNumber,
|
||||
long pinnedUntil,
|
||||
@Nullable RecipientId deletedBy,
|
||||
@Nullable MessageExtras messageExtras)
|
||||
{
|
||||
super(body, fromRecipient, toRecipient, dateSent, dateReceived,
|
||||
@@ -153,12 +153,12 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
this.unidentified = unidentified;
|
||||
this.reactions = reactions;
|
||||
this.serverTimestamp = dateServer;
|
||||
this.remoteDelete = remoteDelete;
|
||||
this.notifiedTimestamp = notifiedTimestamp;
|
||||
this.receiptTimestamp = receiptTimestamp;
|
||||
this.originalMessageId = originalMessageId;
|
||||
this.revisionNumber = revisionNumber;
|
||||
this.pinnedUntil = pinnedUntil;
|
||||
this.deletedBy = deletedBy;
|
||||
this.messageExtras = messageExtras;
|
||||
}
|
||||
|
||||
@@ -785,6 +785,10 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
return pinnedUntil;
|
||||
}
|
||||
|
||||
public @Nullable RecipientId getDeletedBy() {
|
||||
return deletedBy;
|
||||
}
|
||||
|
||||
public boolean isInMemoryMessageRecord() {
|
||||
return false;
|
||||
}
|
||||
@@ -832,7 +836,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
}
|
||||
|
||||
public boolean isRemoteDelete() {
|
||||
return remoteDelete;
|
||||
return deletedBy != null;
|
||||
}
|
||||
|
||||
public @NonNull List<ReactionRecord> getReactions() {
|
||||
|
||||
@@ -103,7 +103,6 @@ public class MmsMessageRecord extends MessageRecord {
|
||||
@NonNull List<LinkPreview> linkPreviews,
|
||||
boolean unidentified,
|
||||
@NonNull List<ReactionRecord> reactions,
|
||||
boolean remoteDelete,
|
||||
boolean mentionsSelf,
|
||||
long notifiedTimestamp,
|
||||
boolean viewed,
|
||||
@@ -121,12 +120,13 @@ public class MmsMessageRecord extends MessageRecord {
|
||||
int revisionNumber,
|
||||
boolean isRead,
|
||||
long pinnedUntil,
|
||||
@Nullable RecipientId deletedBy,
|
||||
@Nullable MessageExtras messageExtras)
|
||||
{
|
||||
super(id, body, fromRecipient, fromDeviceId, toRecipient,
|
||||
dateSent, dateReceived, dateServer, threadId, Status.STATUS_NONE, hasDeliveryReceipt,
|
||||
mailbox, mismatches, failures, subscriptionId, expiresIn, expireStarted, expireTimerVersion, hasReadReceipt,
|
||||
unidentified, reactions, remoteDelete, notifiedTimestamp, viewed, receiptTimestamp, originalMessageId, revisionNumber, pinnedUntil, messageExtras);
|
||||
unidentified, reactions, notifiedTimestamp, viewed, receiptTimestamp, originalMessageId, revisionNumber, pinnedUntil, deletedBy, messageExtras);
|
||||
|
||||
this.slideDeck = slideDeck;
|
||||
this.quote = quote;
|
||||
@@ -337,17 +337,17 @@ public class MmsMessageRecord extends MessageRecord {
|
||||
public @NonNull MmsMessageRecord withReactions(@NonNull List<ReactionRecord> reactions) {
|
||||
return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), hasDeliveryReceipt(), getThreadId(), getBody(), getSlideDeck(),
|
||||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), getExpireTimerVersion(), isViewOnce(),
|
||||
hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), reactions, isRemoteDelete(), mentionsSelf,
|
||||
hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), reactions, mentionsSelf,
|
||||
getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getPoll(), getScheduledDate(), getLatestRevisionId(),
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getPinnedUntil(), getMessageExtras());
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getPinnedUntil(), getDeletedBy(), getMessageExtras());
|
||||
}
|
||||
|
||||
public @NonNull MmsMessageRecord withoutQuote() {
|
||||
return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), hasDeliveryReceipt(), getThreadId(), getBody(), getSlideDeck(),
|
||||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), getExpireTimerVersion(), isViewOnce(),
|
||||
hasReadReceipt(), null, getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
|
||||
hasReadReceipt(), null, getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), mentionsSelf,
|
||||
getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getPoll(), getScheduledDate(), getLatestRevisionId(),
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getPinnedUntil(), getMessageExtras());
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getPinnedUntil(), getDeletedBy(), getMessageExtras());
|
||||
}
|
||||
|
||||
public @NonNull MmsMessageRecord withAttachments(@NonNull List<DatabaseAttachment> attachments) {
|
||||
@@ -367,34 +367,34 @@ public class MmsMessageRecord extends MessageRecord {
|
||||
|
||||
return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), hasDeliveryReceipt(), getThreadId(), getBody(), slideDeck,
|
||||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), getExpireTimerVersion(), isViewOnce(),
|
||||
hasReadReceipt(), quote, contacts, linkPreviews, isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
|
||||
hasReadReceipt(), quote, contacts, linkPreviews, isUnidentified(), getReactions(), mentionsSelf,
|
||||
getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getPoll(), getScheduledDate(), getLatestRevisionId(),
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getPinnedUntil(), getMessageExtras());
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getPinnedUntil(), getDeletedBy(), getMessageExtras());
|
||||
}
|
||||
|
||||
public @NonNull MmsMessageRecord withPayment(@NonNull Payment payment) {
|
||||
return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), hasDeliveryReceipt(), getThreadId(), getBody(), getSlideDeck(),
|
||||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), getExpireTimerVersion(), isViewOnce(),
|
||||
hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
|
||||
hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), mentionsSelf,
|
||||
getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), payment, getCall(), getPoll(), getScheduledDate(), getLatestRevisionId(),
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getPinnedUntil(), getMessageExtras());
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getPinnedUntil(), getDeletedBy(), getMessageExtras());
|
||||
}
|
||||
|
||||
|
||||
public @NonNull MmsMessageRecord withCall(@Nullable CallTable.Call call) {
|
||||
return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), hasDeliveryReceipt(), getThreadId(), getBody(), getSlideDeck(),
|
||||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), getExpireTimerVersion(), isViewOnce(),
|
||||
hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
|
||||
hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), mentionsSelf,
|
||||
getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), call, getPoll(), getScheduledDate(), getLatestRevisionId(),
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getPinnedUntil(), getMessageExtras());
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getPinnedUntil(), getDeletedBy(), getMessageExtras());
|
||||
}
|
||||
|
||||
public @NonNull MmsMessageRecord withPoll(@Nullable PollRecord poll) {
|
||||
return new MmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), hasDeliveryReceipt(), getThreadId(), getBody(), getSlideDeck(),
|
||||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), getExpireTimerVersion(), isViewOnce(),
|
||||
hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
|
||||
hasReadReceipt(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), mentionsSelf,
|
||||
getNotifiedTimestamp(), isViewed(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), poll, getScheduledDate(), getLatestRevisionId(),
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getPinnedUntil(), getMessageExtras());
|
||||
getOriginalMessageId(), getRevisionNumber(), isRead(), getPinnedUntil(), getDeletedBy(), getMessageExtras());
|
||||
}
|
||||
|
||||
private static @NonNull List<Contact> updateContacts(@NonNull List<Contact> contacts, @NonNull Map<AttachmentId, DatabaseAttachment> attachmentIdMap) {
|
||||
|
||||
@@ -209,6 +209,14 @@ public final class ThreadRecord {
|
||||
}
|
||||
}
|
||||
|
||||
public @NonNull RecipientId getDeletedByRecipientId() {
|
||||
if (extra != null && extra.getDeletedBy() != null) {
|
||||
return RecipientId.from(extra.getDeletedBy());
|
||||
} else {
|
||||
return RecipientId.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
public @NonNull RecipientId getGroupMessageSender() {
|
||||
RecipientId threadRecipientId = getRecipient().getId();
|
||||
RecipientId individualRecipientId = getIndividualRecipientId();
|
||||
|
||||
Reference in New Issue
Block a user