Move to defined from_recipient_id and to_recipient_id columns on message table.

This commit is contained in:
Greyson Parrelli
2023-04-14 14:23:05 -04:00
committed by Cody Henthorne
parent d079f85eca
commit 279ad7945e
86 changed files with 944 additions and 719 deletions

View File

@@ -88,7 +88,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
val messageType: Long = Call.getMessageType(type, direction, event)
writableDatabase.withinTransaction {
val result = SignalDatabase.messages.insertCallLog(peer, messageType, timestamp)
val result = SignalDatabase.messages.insertCallLog(peer, messageType, timestamp, direction == Direction.OUTGOING)
val values = contentValuesOf(
CALL_ID to callId,

View File

@@ -9,35 +9,30 @@ import org.thoughtcrime.securesms.util.LRUCache;
import java.util.HashMap;
import java.util.Map;
public class EarlyReceiptCache {
public class EarlyDeliveryReceiptCache {
private static final String TAG = Log.tag(EarlyReceiptCache.class);
private static final String TAG = Log.tag(EarlyDeliveryReceiptCache.class);
private final LRUCache<Long, Map<RecipientId, Receipt>> cache = new LRUCache<>(100);
private final String name;
public EarlyReceiptCache(@NonNull String name) {
this.name = name;
}
public synchronized void increment(long timestamp, @NonNull RecipientId origin, long receiptTimestamp) {
Map<RecipientId, Receipt> receipts = cache.get(timestamp);
public synchronized void increment(long targetTimestamp, @NonNull RecipientId receiptAuthor, long receiptSentTimestamp) {
Map<RecipientId, Receipt> receipts = cache.get(targetTimestamp);
if (receipts == null) {
receipts = new HashMap<>();
}
Receipt receipt = receipts.get(origin);
Receipt receipt = receipts.get(receiptAuthor);
if (receipt != null) {
receipt.count++;
receipt.timestamp = receiptTimestamp;
receipt.timestamp = receiptSentTimestamp;
} else {
receipt = new Receipt(1, receiptTimestamp);
receipt = new Receipt(1, receiptSentTimestamp);
}
receipts.put(origin, receipt);
receipts.put(receiptAuthor, receipt);
cache.put(timestamp, receipts);
cache.put(targetTimestamp, receipts);
}
public synchronized Map<RecipientId, Receipt> remove(long timestamp) {
@@ -45,7 +40,7 @@ public class EarlyReceiptCache {
return receipts != null ? receipts : new HashMap<>();
}
public class Receipt {
public static class Receipt {
private long count;
private long timestamp;

View File

@@ -1275,7 +1275,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
SELECT ${MessageTable.TABLE_NAME}.${MessageTable.DATE_RECEIVED}
FROM ${MessageTable.TABLE_NAME}
WHERE
${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID} = ${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} AND
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID} = ${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} AND
${MessageTable.STORY_TYPE} > 1
ORDER BY ${MessageTable.TABLE_NAME}.${MessageTable.DATE_RECEIVED} DESC
LIMIT 1

View File

@@ -54,7 +54,7 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
${MessageTable.TABLE_NAME}.${MessageTable.DATE_RECEIVED},
${MessageTable.TABLE_NAME}.${MessageTable.DATE_SERVER},
${MessageTable.TABLE_NAME}.${MessageTable.THREAD_ID},
${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID},
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID},
${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} as $THREAD_RECIPIENT_ID
FROM
${AttachmentTable.TABLE_NAME}
@@ -78,7 +78,7 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
)
) AND
${AttachmentTable.STICKER_PACK_ID} IS NULL AND
${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID} > 0 AND
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID} > 0 AND
$THREAD_RECIPIENT_ID > 0
""".toSingleLine()
@@ -204,7 +204,7 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
return MediaRecord(
attachment = if (attachments.isNotEmpty()) attachments[0] else null,
recipientId = RecipientId.from(cursor.requireLong(MessageTable.RECIPIENT_ID)),
recipientId = RecipientId.from(cursor.requireLong(MessageTable.FROM_RECIPIENT_ID)),
threadId = cursor.requireLong(MessageTable.THREAD_ID),
threadRecipientId = RecipientId.from(cursor.requireLong(THREAD_RECIPIENT_ID)),
date = if (MessageTypes.isPushType(cursor.requireLong(MessageTable.TYPE))) {

View File

@@ -63,7 +63,7 @@ class SearchTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
private const val MESSAGES_QUERY = """
SELECT
${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} AS $CONVERSATION_RECIPIENT,
${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID} AS $MESSAGE_RECIPIENT,
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID} AS $MESSAGE_RECIPIENT,
snippet($FTS_TABLE_NAME, -1, '', '', '$SNIPPET_WRAP', 7) AS $SNIPPET,
${MessageTable.TABLE_NAME}.${MessageTable.DATE_RECEIVED},
$FTS_TABLE_NAME.$THREAD_ID,
@@ -86,7 +86,7 @@ class SearchTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
private const val MESSAGES_FOR_THREAD_QUERY = """
SELECT
${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} AS $CONVERSATION_RECIPIENT,
${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID} AS $MESSAGE_RECIPIENT,
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID} AS $MESSAGE_RECIPIENT,
snippet($FTS_TABLE_NAME, -1, '', '', '$SNIPPET_WRAP', 7) AS $SNIPPET,
${MessageTable.TABLE_NAME}.${MessageTable.DATE_RECEIVED},
$FTS_TABLE_NAME.$THREAD_ID,

View File

@@ -171,14 +171,14 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
}
}
fun getStoryMessagesFor(syncMessageId: MessageTable.SyncMessageId): Set<MessageId> {
fun getStoryMessagesFor(recipientId: RecipientId, sentTimestamp: Long): Set<MessageId> {
val messageIds = mutableSetOf<MessageId>()
readableDatabase.query(
TABLE_NAME,
arrayOf(MESSAGE_ID),
"$RECIPIENT_ID = ? AND $SENT_TIMESTAMP = ?",
SqlUtil.buildArgs(syncMessageId.recipientId, syncMessageId.timetamp),
SqlUtil.buildArgs(recipientId, sentTimestamp),
null,
null,
null
@@ -270,7 +270,7 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
val query = """
SELECT ${MessageTable.TABLE_NAME}.${MessageTable.ID} as $MESSAGE_ID, ${DistributionListTables.DISTRIBUTION_ID}
FROM ${MessageTable.TABLE_NAME}
INNER JOIN ${DistributionListTables.LIST_TABLE_NAME} ON ${DistributionListTables.LIST_TABLE_NAME}.${DistributionListTables.RECIPIENT_ID} = ${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID}
INNER JOIN ${DistributionListTables.LIST_TABLE_NAME} ON ${DistributionListTables.LIST_TABLE_NAME}.${DistributionListTables.RECIPIENT_ID} = ${MessageTable.TABLE_NAME}.${MessageTable.TO_RECIPIENT_ID}
WHERE ${MessageTable.DATE_SENT} = $sentTimestamp AND ${DistributionListTables.DISTRIBUTION_ID} IS NOT NULL
""".trimIndent()

View File

@@ -91,11 +91,11 @@ public final class ThreadBodyUtil {
private static @NonNull String getGiftSummary(@NonNull Context context, @NonNull MessageRecord messageRecord) {
if (messageRecord.isOutgoing()) {
return context.getString(R.string.ThreadRecord__you_donated_for_s, messageRecord.getRecipient().getShortDisplayName(context));
return context.getString(R.string.ThreadRecord__you_donated_for_s, messageRecord.getToRecipient().getShortDisplayName(context));
} else if (messageRecord.getViewedReceiptCount() > 0) {
return context.getString(R.string.ThreadRecord__you_redeemed_a_badge);
} else {
return context.getString(R.string.ThreadRecord__s_donated_for_you, messageRecord.getRecipient().getShortDisplayName(context));
return context.getString(R.string.ThreadRecord__s_donated_for_you, messageRecord.getFromRecipient().getShortDisplayName(context));
}
}
@@ -111,7 +111,7 @@ public final class ThreadBodyUtil {
if (messageRecord.isOutgoing()) {
return context.getString(R.string.ThreadRecord_you_sent_request);
} else {
return context.getString(R.string.ThreadRecord_wants_you_to_activate_payments, messageRecord.getRecipient().getShortDisplayName(context));
return context.getString(R.string.ThreadRecord_wants_you_to_activate_payments, messageRecord.getFromRecipient().getShortDisplayName(context));
}
}
@@ -119,7 +119,7 @@ public final class ThreadBodyUtil {
if (messageRecord.isOutgoing()) {
return context.getString(R.string.ThreadRecord_you_activated_payments);
} else {
return context.getString(R.string.ThreadRecord_can_accept_payments, messageRecord.getRecipient().getShortDisplayName(context));
return context.getString(R.string.ThreadRecord_can_accept_payments, messageRecord.getFromRecipient().getShortDisplayName(context));
}
}

View File

@@ -1359,6 +1359,11 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
}
private fun update(threadId: Long, unarchive: Boolean, allowDeletion: Boolean, notifyListeners: Boolean): Boolean {
if (threadId == -1L) {
Log.d(TAG, "Skipping update for threadId -1")
return false
}
val meaningfulMessages = messages.hasMeaningfulMessage(threadId)
val isPinned = getPinnedThreadIds().contains(threadId)
@@ -1581,10 +1586,10 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
}
private fun getExtrasFor(record: MessageRecord, body: ThreadBody): Extra? {
val threadRecipient = if (record.isOutgoing) record.recipient else getRecipientForThreadId(record.threadId)
val threadRecipient = getRecipientForThreadId(record.threadId)
val messageRequestAccepted = RecipientUtil.isMessageRequestAccepted(record.threadId, threadRecipient)
val isHidden = threadRecipient?.isHidden ?: false
val individualRecipientId = record.individualRecipient.id
val authorId = record.fromRecipient.id
if (!messageRequestAccepted && threadRecipient != null) {
if (threadRecipient.isPushGroup) {
@@ -1594,46 +1599,46 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
val from = RecipientId.from(ServiceId.from(inviteAddState.addedOrInvitedBy))
return if (inviteAddState.isInvited) {
Log.i(TAG, "GV2 invite message request from $from")
Extra.forGroupV2invite(from, individualRecipientId)
Extra.forGroupV2invite(from, authorId)
} else {
Log.i(TAG, "GV2 message request from $from")
Extra.forGroupMessageRequest(from, individualRecipientId)
Extra.forGroupMessageRequest(from, authorId)
}
}
Log.w(TAG, "Falling back to unknown message request state for GV2 message")
return Extra.forMessageRequest(individualRecipientId)
return Extra.forMessageRequest(authorId)
} else {
val recipientId = messages.getGroupAddedBy(record.threadId)
if (recipientId != null) {
return Extra.forGroupMessageRequest(recipientId, individualRecipientId)
return Extra.forGroupMessageRequest(recipientId, authorId)
}
}
} else {
return Extra.forMessageRequest(individualRecipientId, isHidden)
return Extra.forMessageRequest(authorId, isHidden)
}
}
val extras: Extra? = if (record.isScheduled()) {
Extra.forScheduledMessage(individualRecipientId)
Extra.forScheduledMessage(authorId)
} else if (record.isRemoteDelete) {
Extra.forRemoteDelete(individualRecipientId)
Extra.forRemoteDelete(authorId)
} else if (record.isViewOnce) {
Extra.forViewOnce(individualRecipientId)
Extra.forViewOnce(authorId)
} else if (record.isMms && (record as MmsMessageRecord).slideDeck.stickerSlide != null) {
val slide: StickerSlide = record.slideDeck.stickerSlide!!
Extra.forSticker(slide.emoji, individualRecipientId)
Extra.forSticker(slide.emoji, authorId)
} else if (record.isMms && (record as MmsMessageRecord).slideDeck.slides.size > 1) {
Extra.forAlbum(individualRecipientId)
Extra.forAlbum(authorId)
} else if (threadRecipient != null && threadRecipient.isGroup) {
Extra.forDefault(individualRecipientId)
Extra.forDefault(authorId)
} else {
null
}
return if (record.messageRanges != null) {
val bodyRanges = record.requireMessageRanges().adjustBodyRanges(body.bodyAdjustments)!!
extras?.copy(bodyRanges = bodyRanges.serialize()) ?: Extra.forBodyRanges(bodyRanges, individualRecipientId)
extras?.copy(bodyRanges = bodyRanges.serialize()) ?: Extra.forBodyRanges(bodyRanges, authorId)
} else {
extras
}

View File

@@ -40,6 +40,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V181_ThreadTableFor
import org.thoughtcrime.securesms.database.helpers.migration.V182_CallTableMigration
import org.thoughtcrime.securesms.database.helpers.migration.V183_CallLinkTableMigration
import org.thoughtcrime.securesms.database.helpers.migration.V184_CallLinkReplaceIndexMigration
import org.thoughtcrime.securesms.database.helpers.migration.V185_MessageRecipientsMigration
/**
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
@@ -48,7 +49,7 @@ object SignalDatabaseMigrations {
val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass)
const val DATABASE_VERSION = 184
const val DATABASE_VERSION = 185
@JvmStatic
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
@@ -195,6 +196,10 @@ object SignalDatabaseMigrations {
if (oldVersion < 184) {
V184_CallLinkReplaceIndexMigration.migrate(context, db, oldVersion, newVersion)
}
if (oldVersion < 185) {
V185_MessageRecipientsMigration.migrate(context, db, oldVersion, newVersion)
}
}
@JvmStatic

View File

@@ -0,0 +1,285 @@
package org.thoughtcrime.securesms.database.helpers.migration
import android.app.Application
import android.preference.PreferenceManager
import net.zetetic.database.sqlcipher.SQLiteDatabase
import org.signal.core.util.SqlUtil
import org.signal.core.util.Stopwatch
import org.signal.core.util.logging.Log
import org.signal.core.util.readToList
import org.signal.core.util.readToSingleInt
import org.signal.core.util.readToSingleObject
import org.signal.core.util.requireLong
import org.signal.core.util.requireNonNullString
import org.signal.core.util.requireString
import org.signal.core.util.toSingleLine
import org.thoughtcrime.securesms.database.KeyValueDatabase
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.recipients.RecipientId
import org.whispersystems.signalservice.api.push.ACI
/**
* Our current column setup for knowing is the the sender/receiver of a message is both confusing and non-optimal from a performance perspective.
* This moves to a world where instead of tracking a single recipient, we track two: a sender and receiver.
*/
object V185_MessageRecipientsMigration : SignalDatabaseMigration {
private val TAG = Log.tag(V185_MessageRecipientsMigration::class.java)
private val outgoingClause = "(" + listOf(21, 23, 22, 24, 25, 26, 2, 11)
.map { "type & ${0x1F} = $it" }
.joinToString(separator = " OR ") + ")"
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
val stopwatch = Stopwatch("migration")
val selfId: RecipientId? = getSelfId(db)
if (selfId == null) {
val messageCount = db.rawQuery("SELECT COUNT(*) FROM message").readToSingleInt()
if (messageCount == 0) {
Log.i(TAG, "Could not find ourselves in the DB! Assuming this is an install that hasn't been registered yet.")
} else {
throw IllegalStateException("Could not find ourselves in the recipient table, but messages exist in the message table!")
}
}
stopwatch.split("get-self")
val dependentItems: List<SqlItem> = getAllDependentItems(db, "message")
dependentItems.forEach { item ->
val sql = "DROP ${item.type} IF EXISTS ${item.name}"
Log.d(TAG, "Executing: $sql")
db.execSQL(sql)
}
stopwatch.split("drop-dependents")
db.execSQL(
"""
CREATE TABLE message_tmp (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
date_sent INTEGER NOT NULL,
date_received INTEGER NOT NULL,
date_server INTEGER DEFAULT -1,
thread_id INTEGER NOT NULL REFERENCES thread (_id) ON DELETE CASCADE,
from_recipient_id INTEGER NOT NULL REFERENCES recipient (_id) ON DELETE CASCADE,
from_device_id INTEGER,
to_recipient_id INTEGER NOT NULL REFERENCES recipient (_id) ON DELETE CASCADE,
type INTEGER NOT NULL,
body TEXT,
read INTEGER DEFAULT 0,
ct_l TEXT,
exp INTEGER,
m_type INTEGER,
m_size INTEGER,
st INTEGER,
tr_id TEXT,
subscription_id INTEGER DEFAULT -1,
receipt_timestamp INTEGER DEFAULT -1,
delivery_receipt_count INTEGER DEFAULT 0,
read_receipt_count INTEGER DEFAULT 0,
viewed_receipt_count INTEGER DEFAULT 0,
mismatched_identities TEXT DEFAULT NULL,
network_failures TEXT DEFAULT NULL,
expires_in INTEGER DEFAULT 0,
expire_started INTEGER DEFAULT 0,
notified INTEGER DEFAULT 0,
quote_id INTEGER DEFAULT 0,
quote_author INTEGER DEFAULT 0,
quote_body TEXT DEFAULT NULL,
quote_missing INTEGER DEFAULT 0,
quote_mentions BLOB DEFAULT NULL,
quote_type INTEGER DEFAULT 0,
shared_contacts TEXT DEFAULT NULL,
unidentified INTEGER DEFAULT 0,
link_previews TEXT DEFAULT NULL,
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,
message_ranges BLOB DEFAULT NULL,
story_type INTEGER DEFAULT 0,
parent_story_id INTEGER DEFAULT 0,
export_state BLOB DEFAULT NULL,
exported INTEGER DEFAULT 0,
scheduled_date INTEGER DEFAULT -1
)
"""
)
stopwatch.split("create-table")
db.execSQL(
"""
INSERT INTO message_tmp
SELECT
_id,
date_sent,
date_received,
date_server,
thread_id,
recipient_id,
recipient_device_id,
recipient_id,
type,
body,
read,
ct_l,
exp,
m_type,
m_size,
st,
tr_id,
subscription_id,
receipt_timestamp,
delivery_receipt_count,
read_receipt_count,
viewed_receipt_count,
mismatched_identities,
network_failures,
expires_in,
expire_started,
notified,
quote_id,
quote_author,
quote_body,
quote_missing,
quote_mentions,
quote_type,
shared_contacts,
unidentified,
link_previews,
view_once,
reactions_unread,
reactions_last_seen,
remote_deleted,
mentions_self,
notified_timestamp,
server_guid,
message_ranges,
story_type,
parent_story_id,
export_state,
exported,
scheduled_date
FROM message
"""
)
stopwatch.split("copy-data")
// Previously, the recipient_id on an outgoing message represented who it was going to (an individual or group).
// So if a message is outgoing, we'll set to = from, then from = self
if (selfId != null) {
db.execSQL(
"""
UPDATE message_tmp
SET
to_recipient_id = from_recipient_id,
from_recipient_id = ${selfId.toLong()},
from_device_id = 1
WHERE $outgoingClause
""".toSingleLine()
)
}
stopwatch.split("update-data")
db.execSQL("DROP TABLE message")
stopwatch.split("drop-old-table")
db.execSQL("ALTER TABLE message_tmp RENAME TO message")
stopwatch.split("rename-table")
dependentItems.forEach { item ->
val sql = when (item.name) {
"mms_date_sent_index" -> "CREATE INDEX message_date_sent_from_to_thread_index ON message (date_sent, from_recipient_id, to_recipient_id, thread_id)"
else -> item.createStatement.replace(Regex.fromLiteral("CREATE INDEX mms_"), "CREATE INDEX message_")
}
Log.d(TAG, "Executing: $sql")
db.execSQL(sql)
}
stopwatch.split("recreate-dependents")
db.execSQL("PRAGMA foreign_key_check")
stopwatch.split("fk-check")
stopwatch.stop(TAG)
}
private fun getSelfId(db: SQLiteDatabase): RecipientId? {
val idByAci: RecipientId? = getLocalAci(ApplicationDependencies.getApplication())?.let { aci ->
db.rawQuery("SELECT _id FROM recipient WHERE uuid = ?", SqlUtil.buildArgs(aci))
.readToSingleObject { RecipientId.from(it.requireLong("_id")) }
}
if (idByAci != null) {
return idByAci
}
Log.w(TAG, "Failed to find by ACI! Will try by E164.")
val idByE164: RecipientId? = getLocalE164(ApplicationDependencies.getApplication())?.let { e164 ->
db.rawQuery("SELECT _id FROM recipient WHERE phone = ?", SqlUtil.buildArgs(e164))
.readToSingleObject { RecipientId.from(it.requireLong("_id")) }
}
if (idByE164 == null) {
Log.w(TAG, "Also failed to find by E164!")
}
return idByE164
}
private fun getLocalAci(context: Application): ACI? {
if (KeyValueDatabase.exists(context)) {
val keyValueDatabase = KeyValueDatabase.getInstance(context).readableDatabase
keyValueDatabase.query("key_value", arrayOf("value"), "key = ?", SqlUtil.buildArgs("account.aci"), null, null, null).use { cursor ->
return if (cursor.moveToFirst()) {
ACI.parseOrNull(cursor.requireString("value"))
} else {
Log.w(TAG, "ACI not present in KV database!")
null
}
}
} else {
Log.w(TAG, "Pre-KV database -- searching for ACI in shared prefs.")
return ACI.parseOrNull(PreferenceManager.getDefaultSharedPreferences(context).getString("pref_local_uuid", null))
}
}
private fun getLocalE164(context: Application): String? {
if (KeyValueDatabase.exists(context)) {
val keyValueDatabase = KeyValueDatabase.getInstance(context).readableDatabase
keyValueDatabase.query("key_value", arrayOf("value"), "key = ?", SqlUtil.buildArgs("account.e164"), null, null, null).use { cursor ->
return if (cursor.moveToFirst()) {
cursor.requireString("value")
} else {
Log.w(TAG, "E164 not present in KV database!")
null
}
}
} else {
Log.w(TAG, "Pre-KV database -- searching for E164 in shared prefs.")
return PreferenceManager.getDefaultSharedPreferences(context).getString("pref_local_number", null)
}
}
private fun getAllDependentItems(db: SQLiteDatabase, tableName: String): List<SqlItem> {
return db.rawQuery("SELECT type, name, sql FROM sqlite_schema WHERE tbl_name='$tableName' AND type != 'table'").readToList { cursor ->
SqlItem(
type = cursor.requireNonNullString("type"),
name = cursor.requireNonNullString("name"),
createStatement = cursor.requireNonNullString("sql")
)
}
}
data class SqlItem(
val type: String,
val name: String,
val createStatement: String
)
}

View File

@@ -39,7 +39,8 @@ public abstract class DisplayRecord {
protected final long type;
private final Recipient recipient;
private final Recipient fromRecipient;
private final Recipient toRecipient;
private final long dateSent;
private final long dateReceived;
private final long threadId;
@@ -49,12 +50,13 @@ public abstract class DisplayRecord {
private final int readReceiptCount;
private final int viewReceiptCount;
DisplayRecord(String body, Recipient recipient, long dateSent,
DisplayRecord(String body, Recipient fromRecipient, Recipient toRecipient, long dateSent,
long dateReceived, long threadId, int deliveryStatus, int deliveryReceiptCount,
long type, int readReceiptCount, int viewReceiptCount)
{
this.threadId = threadId;
this.recipient = recipient;
this.fromRecipient = fromRecipient;
this.toRecipient = toRecipient;
this.dateSent = dateSent;
this.dateReceived = dateReceived;
this.type = type;
@@ -97,8 +99,12 @@ public abstract class DisplayRecord {
public abstract SpannableString getDisplayBody(@NonNull Context context);
public Recipient getRecipient() {
return recipient.live().get();
public Recipient getFromRecipient() {
return fromRecipient.live().get();
}
public Recipient getToRecipient() {
return toRecipient.live().get();
}
public long getDateSent() {

View File

@@ -27,15 +27,15 @@ public class InMemoryMessageRecord extends MessageRecord {
private InMemoryMessageRecord(long id,
String body,
Recipient conversationRecipient,
Recipient author,
long threadId,
long type)
{
super(id,
body,
conversationRecipient,
conversationRecipient,
author,
1,
author,
System.currentTimeMillis(),
System.currentTimeMillis(),
System.currentTimeMillis(),
@@ -170,8 +170,8 @@ public class InMemoryMessageRecord extends MessageRecord {
* Useful for create an empty message record when one is needed.
*/
public static final class ForceConversationBubble extends InMemoryMessageRecord {
public ForceConversationBubble(Recipient conversationRecipient, long threadId) {
super(FORCE_BUBBLE_ID, "", conversationRecipient, threadId, 0);
public ForceConversationBubble(Recipient author, long threadId) {
super(FORCE_BUBBLE_ID, "", author, threadId, 0);
}
}
}

View File

@@ -72,9 +72,9 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
private final long scheduledDate;
public MediaMmsMessageRecord(long id,
Recipient conversationRecipient,
Recipient individualRecipient,
int recipientDeviceId,
Recipient fromRecipient,
int fromDeviceId,
Recipient toRecipient,
long dateSent,
long dateReceived,
long dateServer,
@@ -108,7 +108,7 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
@Nullable CallTable.Call call,
long scheduledDate)
{
super(id, body, conversationRecipient, individualRecipient, recipientDeviceId, dateSent,
super(id, body, fromRecipient, fromDeviceId, toRecipient, dateSent,
dateReceived, dateServer, threadId, Status.STATUS_NONE, deliveryReceiptCount, mailbox, mismatches, failures,
subscriptionId, expiresIn, expireStarted, viewOnce, slideDeck,
readReceiptCount, quote, contacts, linkPreviews, unidentified, reactions, remoteDelete, notifiedTimestamp, viewedReceiptCount, receiptTimestamp,
@@ -205,14 +205,14 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
}
public @NonNull MediaMmsMessageRecord withReactions(@NonNull List<ReactionRecord> reactions) {
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
return new MediaMmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
getReadReceiptCount(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), reactions, isRemoteDelete(), mentionsSelf,
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate());
}
public @NonNull MediaMmsMessageRecord withoutQuote() {
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
return new MediaMmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
getReadReceiptCount(), null, getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate());
@@ -233,14 +233,14 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
List<DatabaseAttachment> slideAttachments = attachments.stream().filter(a -> !contactAttachments.contains(a)).filter(a -> !linkPreviewAttachments.contains(a)).collect(Collectors.toList());
SlideDeck slideDeck = MessageTable.MmsReader.buildSlideDeck(context, slideAttachments);
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), slideDeck,
return new MediaMmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), slideDeck,
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
getReadReceiptCount(), quote, contacts, linkPreviews, isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate());
}
public @NonNull MediaMmsMessageRecord withPayment(@NonNull Payment payment) {
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
return new MediaMmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
getReadReceiptCount(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), payment, getCall(), getScheduledDate());
@@ -248,7 +248,7 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
public @NonNull MediaMmsMessageRecord withCall(@Nullable CallTable.Call call) {
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
return new MediaMmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
getReadReceiptCount(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), call, getScheduledDate());

View File

@@ -89,9 +89,8 @@ public abstract class MessageRecord extends DisplayRecord {
private static final String TAG = Log.tag(MessageRecord.class);
private final Recipient individualRecipient;
private final int recipientDeviceId;
private final long id;
private final int authorDeviceId;
private final Set<IdentityKeyMismatch> mismatches;
private final Set<NetworkFailure> networkFailures;
private final int subscriptionId;
@@ -106,8 +105,7 @@ public abstract class MessageRecord extends DisplayRecord {
protected Boolean isJumboji = null;
MessageRecord(long id, String body, Recipient conversationRecipient,
Recipient individualRecipient, int recipientDeviceId,
MessageRecord(long id, String body, Recipient fromRecipient, int fromDeviceId, Recipient toRecipient,
long dateSent, long dateReceived, long dateServer, long threadId,
int deliveryStatus, int deliveryReceiptCount, long type,
Set<IdentityKeyMismatch> mismatches,
@@ -117,12 +115,11 @@ public abstract class MessageRecord extends DisplayRecord {
@NonNull List<ReactionRecord> reactions, boolean remoteDelete, long notifiedTimestamp,
int viewedReceiptCount, long receiptTimestamp)
{
super(body, conversationRecipient, dateSent, dateReceived,
super(body, fromRecipient, toRecipient, dateSent, dateReceived,
threadId, deliveryStatus, deliveryReceiptCount, type,
readReceiptCount, viewedReceiptCount);
this.id = id;
this.individualRecipient = individualRecipient;
this.recipientDeviceId = recipientDeviceId;
this.authorDeviceId = fromDeviceId;
this.mismatches = mismatches;
this.networkFailures = networkFailures;
this.subscriptionId = subscriptionId;
@@ -171,11 +168,11 @@ public abstract class MessageRecord extends DisplayRecord {
} else if (isGroupUpdate() && isOutgoing()) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_you_updated_group), R.drawable.ic_update_group_16);
} else if (isGroupUpdate()) {
return fromRecipient(getIndividualRecipient(), r -> GroupUtil.getNonV2GroupDescription(context, getBody()).toString(r), R.drawable.ic_update_group_16);
return fromRecipient(getFromRecipient(), r -> GroupUtil.getNonV2GroupDescription(context, getBody()).toString(r), R.drawable.ic_update_group_16);
} else if (isGroupQuit() && isOutgoing()) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_left_group), R.drawable.ic_update_group_leave_16);
} else if (isGroupQuit()) {
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.ConversationItem_group_action_left, r.getDisplayName(context)), R.drawable.ic_update_group_leave_16);
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.ConversationItem_group_action_left, r.getDisplayName(context)), R.drawable.ic_update_group_leave_16);
} else if (isIncomingAudioCall()) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(R.string.MessageRecord_incoming_voice_call), getCallDateString(context)), R.drawable.ic_update_audio_call_incoming_16);
} else if (isIncomingVideoCall()) {
@@ -191,47 +188,47 @@ public abstract class MessageRecord extends DisplayRecord {
} else if (isGroupCall()) {
return getGroupCallUpdateDescription(context, getBody(), true);
} else if (isJoined()) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_s_joined_signal, getIndividualRecipient().getDisplayName(context)), R.drawable.ic_update_group_add_16);
return staticUpdateDescription(context.getString(R.string.MessageRecord_s_joined_signal, getFromRecipient().getDisplayName(context)), R.drawable.ic_update_group_add_16);
} else if (isExpirationTimerUpdate()) {
int seconds = (int)(getExpiresIn() / 1000);
if (seconds <= 0) {
return isOutgoing() ? staticUpdateDescription(context.getString(R.string.MessageRecord_you_disabled_disappearing_messages), R.drawable.ic_update_timer_disabled_16)
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, r.getDisplayName(context)), R.drawable.ic_update_timer_disabled_16);
: fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, r.getDisplayName(context)), R.drawable.ic_update_timer_disabled_16);
}
String time = ExpirationUtil.getExpirationDisplayValue(context, seconds);
return isOutgoing() ? staticUpdateDescription(context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time), R.drawable.ic_update_timer_16)
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, r.getDisplayName(context), time), R.drawable.ic_update_timer_16);
: fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, r.getDisplayName(context), time), R.drawable.ic_update_timer_16);
} else if (isIdentityUpdate()) {
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context)), R.drawable.ic_update_safety_number_16);
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context)), R.drawable.ic_update_safety_number_16);
} else if (isIdentityVerified()) {
if (isOutgoing()) return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified, r.getDisplayName(context)), R.drawable.ic_update_verified_16);
else return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified_from_another_device, r.getDisplayName(context)), R.drawable.ic_update_verified_16);
if (isOutgoing()) return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified, r.getDisplayName(context)), R.drawable.ic_update_verified_16);
else return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified_from_another_device, r.getDisplayName(context)), R.drawable.ic_update_verified_16);
} else if (isIdentityDefault()) {
if (isOutgoing()) return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified, r.getDisplayName(context)), R.drawable.ic_update_info_16);
else return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified_from_another_device, r.getDisplayName(context)), R.drawable.ic_update_info_16);
if (isOutgoing()) return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified, r.getDisplayName(context)), R.drawable.ic_update_info_16);
else return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified_from_another_device, r.getDisplayName(context)), R.drawable.ic_update_info_16);
} else if (isProfileChange()) {
return staticUpdateDescription(getProfileChangeDescription(context), R.drawable.ic_update_profile_16);
} else if (isChangeNumber()) {
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_changed_their_phone_number, r.getDisplayName(context)), R.drawable.ic_phone_16);
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_s_changed_their_phone_number, r.getDisplayName(context)), R.drawable.ic_phone_16);
} else if (isBoostRequest()) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_like_this_new_feature_help_support_signal_with_a_one_time_donation), 0);
} else if (isEndSession()) {
if (isOutgoing()) return staticUpdateDescription(context.getString(R.string.SmsMessageRecord_secure_session_reset), R.drawable.ic_update_info_16);
else return fromRecipient(getIndividualRecipient(), r-> context.getString(R.string.SmsMessageRecord_secure_session_reset_s, r.getDisplayName(context)), R.drawable.ic_update_info_16);
else return fromRecipient(getFromRecipient(), r-> context.getString(R.string.SmsMessageRecord_secure_session_reset_s, r.getDisplayName(context)), R.drawable.ic_update_info_16);
} else if (isGroupV1MigrationEvent()) {
return getGroupMigrationEventDescription(context);
} else if (isChatSessionRefresh()) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_chat_session_refreshed), R.drawable.ic_refresh_16);
} else if (isBadDecryptType()) {
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_a_message_from_s_couldnt_be_delivered, r.getDisplayName(context)), R.drawable.ic_error_outline_14);
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_a_message_from_s_couldnt_be_delivered, r.getDisplayName(context)), R.drawable.ic_error_outline_14);
} else if (isThreadMergeEventType()) {
try {
ThreadMergeEvent event = ThreadMergeEvent.parseFrom(Base64.decodeOrThrow(getBody()));
if (event.getPreviousE164().isEmpty()) {
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_your_message_history_with_s_and_another_chat_has_been_merged, r.getDisplayName(context)), R.drawable.ic_thread_merge_16);
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_your_message_history_with_s_and_another_chat_has_been_merged, r.getDisplayName(context)), R.drawable.ic_thread_merge_16);
} else {
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_your_message_history_with_s_and_their_number_s_has_been_merged, r.getDisplayName(context), PhoneNumberFormatter.prettyPrint(event.getPreviousE164())), R.drawable.ic_thread_merge_16);
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_your_message_history_with_s_and_their_number_s_has_been_merged, r.getDisplayName(context), PhoneNumberFormatter.prettyPrint(event.getPreviousE164())), R.drawable.ic_thread_merge_16);
}
} catch (InvalidProtocolBufferException e) {
throw new AssertionError(e);
@@ -241,9 +238,9 @@ public abstract class MessageRecord extends DisplayRecord {
SessionSwitchoverEvent event = SessionSwitchoverEvent.parseFrom(Base64.decodeOrThrow(getBody()));
if (event.getE164().isEmpty()) {
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context)), R.drawable.ic_update_safety_number_16);
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context)), R.drawable.ic_update_safety_number_16);
} else {
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_belongs_to_s, PhoneNumberFormatter.prettyPrint(r.requireE164()), r.getDisplayName(context)), R.drawable.ic_update_info_16);
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_s_belongs_to_s, PhoneNumberFormatter.prettyPrint(r.requireE164()), r.getDisplayName(context)), R.drawable.ic_update_info_16);
}
} catch (InvalidProtocolBufferException e) {
throw new AssertionError(e);
@@ -251,13 +248,13 @@ public abstract class MessageRecord extends DisplayRecord {
} else if (isSmsExportType()) {
int messageResource = SignalStore.misc().getSmsExportPhase().isSmsSupported() ? R.string.MessageRecord__you_will_no_longer_be_able_to_send_sms_messages_from_signal_soon
: R.string.MessageRecord__you_can_no_longer_send_sms_messages_in_signal;
return fromRecipient(getIndividualRecipient(), r -> context.getString(messageResource, r.getDisplayName(context)), R.drawable.ic_update_info_16);
return fromRecipient(getFromRecipient(), r -> context.getString(messageResource, r.getDisplayName(context)), R.drawable.ic_update_info_16);
} else if (isPaymentsRequestToActivate()) {
return isOutgoing() ? fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_sent_request, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments)
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_wants_you_to_activate_payments, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments);
return isOutgoing() ? fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_you_sent_request, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments)
: fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_wants_you_to_activate_payments, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments);
} else if (isPaymentsActivated()) {
return isOutgoing() ? staticUpdateDescription(context.getString(R.string.MessageRecord_you_activated_payments), R.drawable.ic_card_activate_payments)
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_can_accept_payments, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments);
: fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_can_accept_payments, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments);
}
return null;
@@ -383,11 +380,11 @@ public abstract class MessageRecord extends DisplayRecord {
ProfileChangeDetails profileChangeDetails = ProfileChangeDetails.parseFrom(decoded);
if (profileChangeDetails.hasProfileNameChange()) {
String displayName = getIndividualRecipient().getDisplayName(context);
String displayName = getFromRecipient().getDisplayName(context);
String newName = StringUtil.isolateBidi(ProfileName.fromSerialized(profileChangeDetails.getProfileNameChange().getNew()).toString());
String previousName = StringUtil.isolateBidi(ProfileName.fromSerialized(profileChangeDetails.getProfileNameChange().getPrevious()).toString());
if (getIndividualRecipient().isSystemContact()) {
if (getFromRecipient().isSystemContact()) {
return context.getString(R.string.MessageRecord_changed_their_profile_name_from_to, displayName, previousName, newName);
} else {
return context.getString(R.string.MessageRecord_changed_their_profile_name_to, previousName, newName);
@@ -397,7 +394,7 @@ public abstract class MessageRecord extends DisplayRecord {
Log.w(TAG, "Profile name change details could not be read", e);
}
return context.getString(R.string.MessageRecord_changed_their_profile, getIndividualRecipient().getDisplayName(context));
return context.getString(R.string.MessageRecord_changed_their_profile, getFromRecipient().getDisplayName(context));
}
private UpdateDescription getGroupMigrationEventDescription(@NonNull Context context) {
@@ -600,12 +597,8 @@ public abstract class MessageRecord extends DisplayRecord {
return false;
}
public Recipient getIndividualRecipient() {
return individualRecipient.live().get();
}
public int getRecipientDeviceId() {
return recipientDeviceId;
public int getFromDeviceId() {
return authorDeviceId;
}
public long getType() {
@@ -625,7 +618,7 @@ public abstract class MessageRecord extends DisplayRecord {
}
public boolean hasFailedWithNetworkFailures() {
return isFailed() && ((getRecipient().isPushGroup() && hasNetworkFailures()) || !isIdentityMismatchFailure());
return isFailed() && ((getToRecipient().isPushGroup() && hasNetworkFailures()) || !isIdentityMismatchFailure());
}
public boolean isChatSessionRefresh() {

View File

@@ -29,8 +29,7 @@ public abstract class MmsMessageRecord extends MessageRecord {
private final boolean viewOnce;
MmsMessageRecord(long id, String body, Recipient conversationRecipient,
Recipient individualRecipient, int recipientDeviceId, long dateSent,
MmsMessageRecord(long id, String body, Recipient fromRecipient, int fromDeviceId, Recipient toRecipient, long dateSent,
long dateReceived, long dateServer, long threadId, int deliveryStatus, int deliveryReceiptCount,
long type, Set<IdentityKeyMismatch> mismatches,
Set<NetworkFailure> networkFailures, int subscriptionId, long expiresIn,
@@ -42,7 +41,7 @@ public abstract class MmsMessageRecord extends MessageRecord {
int viewedReceiptCount, long receiptTimestamp, @NonNull StoryType storyType,
@Nullable ParentStoryId parentStoryId, @Nullable GiftBadge giftBadge)
{
super(id, body, conversationRecipient, individualRecipient, recipientDeviceId,
super(id, body, fromRecipient, fromDeviceId, toRecipient,
dateSent, dateReceived, dateServer, threadId, deliveryStatus, deliveryReceiptCount,
type, mismatches, networkFailures, subscriptionId, expiresIn, expireStarted, readReceiptCount,
unidentified, reactions, remoteDelete, notifiedTimestamp, viewedReceiptCount, receiptTimestamp);

View File

@@ -48,8 +48,7 @@ public class NotificationMmsMessageRecord extends MmsMessageRecord {
private final int status;
private final byte[] transactionId;
public NotificationMmsMessageRecord(long id, Recipient conversationRecipient,
Recipient individualRecipient, int recipientDeviceId,
public NotificationMmsMessageRecord(long id, Recipient fromRecipient, int fromDeviceId, Recipient toRecipient,
long dateSent, long dateReceived, int deliveryReceiptCount,
long threadId, byte[] contentLocation, long messageSize,
long expiry, int status, byte[] transactionId, long mailbox,
@@ -57,7 +56,7 @@ public class NotificationMmsMessageRecord extends MmsMessageRecord {
int viewedReceiptCount, long receiptTimestamp, @NonNull StoryType storyType,
@Nullable ParentStoryId parentStoryId, @Nullable GiftBadge giftBadge)
{
super(id, "", conversationRecipient, individualRecipient, recipientDeviceId,
super(id, "", fromRecipient, fromDeviceId, toRecipient,
dateSent, dateReceived, -1, threadId, Status.STATUS_NONE, deliveryReceiptCount, mailbox,
new HashSet<>(), new HashSet<>(), subscriptionId,
0, 0, false, slideDeck, readReceiptCount, null, Collections.emptyList(), Collections.emptyList(), false,