mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 09:20:19 +01:00
Fix several over-the-wire story issues.
Co-authored-by: Rashad Sookram <rashad@signal.org>
This commit is contained in:
@@ -54,6 +54,7 @@ import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.Quote;
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.StoryViewState;
|
||||
import org.thoughtcrime.securesms.database.model.ParentStoryId;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange;
|
||||
@@ -813,7 +814,7 @@ public class MmsDatabase extends MessageDatabase {
|
||||
public int getMessageCountForThread(long threadId) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
|
||||
|
||||
String query = THREAD_ID + " = ? AND " + IS_STORY + " = ? AND " + PARENT_STORY_ID + " = ?";
|
||||
String query = THREAD_ID + " = ? AND " + IS_STORY + " = ? AND " + PARENT_STORY_ID + " <= ?";
|
||||
String[] args = SqlUtil.buildArgs(threadId, 0, 0);
|
||||
|
||||
try (Cursor cursor = db.query(TABLE_NAME, COUNT, query, args, null, null, null)) {
|
||||
@@ -829,7 +830,7 @@ public class MmsDatabase extends MessageDatabase {
|
||||
public int getMessageCountForThread(long threadId, long beforeTime) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
|
||||
|
||||
String query = THREAD_ID + " = ? AND " + DATE_RECEIVED + " < ? AND " + IS_STORY + " = ? AND " + PARENT_STORY_ID + " = ?";
|
||||
String query = THREAD_ID + " = ? AND " + DATE_RECEIVED + " < ? AND " + IS_STORY + " = ? AND " + PARENT_STORY_ID + " <= ?";
|
||||
String[] args = SqlUtil.buildArgs(threadId, beforeTime, 0, 0);
|
||||
|
||||
try (Cursor cursor = db.query(TABLE_NAME, COUNT, query, args, null, null, null)) {
|
||||
@@ -1207,20 +1208,20 @@ public class MmsDatabase extends MessageDatabase {
|
||||
@Override
|
||||
public List<MarkedMessageInfo> setMessagesReadSince(long threadId, long sinceTimestamp) {
|
||||
if (sinceTimestamp == -1) {
|
||||
return setMessagesRead(THREAD_ID + " = ? AND " + IS_STORY + " = 0 AND " + PARENT_STORY_ID + " = 0 AND (" + READ + " = 0 OR (" + REACTIONS_UNREAD + " = 1 AND (" + getOutgoingTypeClause() + ")))", new String[] {String.valueOf(threadId)});
|
||||
return setMessagesRead(THREAD_ID + " = ? AND " + IS_STORY + " = 0 AND " + PARENT_STORY_ID + " <= 0 AND (" + READ + " = 0 OR (" + REACTIONS_UNREAD + " = 1 AND (" + getOutgoingTypeClause() + ")))", new String[] {String.valueOf(threadId)});
|
||||
} else {
|
||||
return setMessagesRead(THREAD_ID + " = ? AND " + IS_STORY + " = 0 AND " + PARENT_STORY_ID + " = 0 AND (" + READ + " = 0 OR (" + REACTIONS_UNREAD + " = 1 AND ( " + getOutgoingTypeClause() + " ))) AND " + DATE_RECEIVED + " <= ?", new String[]{String.valueOf(threadId), String.valueOf(sinceTimestamp)});
|
||||
return setMessagesRead(THREAD_ID + " = ? AND " + IS_STORY + " = 0 AND " + PARENT_STORY_ID + " <= 0 AND (" + READ + " = 0 OR (" + REACTIONS_UNREAD + " = 1 AND ( " + getOutgoingTypeClause() + " ))) AND " + DATE_RECEIVED + " <= ?", new String[]{String.valueOf(threadId), String.valueOf(sinceTimestamp)});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MarkedMessageInfo> setEntireThreadRead(long threadId) {
|
||||
return setMessagesRead(THREAD_ID + " = ? AND " + IS_STORY + " = 0 AND " + PARENT_STORY_ID + " = 0", new String[] {String.valueOf(threadId)});
|
||||
return setMessagesRead(THREAD_ID + " = ? AND " + IS_STORY + " = 0 AND " + PARENT_STORY_ID + " <= 0", new String[] {String.valueOf(threadId)});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MarkedMessageInfo> setAllMessagesRead() {
|
||||
return setMessagesRead(IS_STORY+ " = 0 AND " + PARENT_STORY_ID + " = 0 AND (" + READ + " = 0 OR (" + REACTIONS_UNREAD + " = 1 AND (" + getOutgoingTypeClause() + ")))", null);
|
||||
return setMessagesRead(IS_STORY+ " = 0 AND " + PARENT_STORY_ID + " <= 0 AND (" + READ + " = 0 OR (" + REACTIONS_UNREAD + " = 1 AND (" + getOutgoingTypeClause() + ")))", null);
|
||||
}
|
||||
|
||||
private List<MarkedMessageInfo> setMessagesRead(String where, String[] arguments) {
|
||||
@@ -1419,7 +1420,7 @@ public class MmsDatabase extends MessageDatabase {
|
||||
String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.MISMATCHED_IDENTITIES));
|
||||
String networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.NETWORK_FAILURE));
|
||||
boolean isStory = CursorUtil.requireBoolean(cursor, IS_STORY);
|
||||
MessageId parentStoryId = MessageId.fromNullable(CursorUtil.requireLong(cursor, PARENT_STORY_ID), true);
|
||||
ParentStoryId parentStoryId = ParentStoryId.deserialize(CursorUtil.requireLong(cursor, PARENT_STORY_ID));
|
||||
|
||||
long quoteId = cursor.getLong(cursor.getColumnIndexOrThrow(QUOTE_ID));
|
||||
long quoteAuthor = cursor.getLong(cursor.getColumnIndexOrThrow(QUOTE_AUTHOR));
|
||||
@@ -1590,7 +1591,7 @@ public class MmsDatabase extends MessageDatabase {
|
||||
contentValues.put(EXPIRES_IN, retrieved.getExpiresIn());
|
||||
contentValues.put(VIEW_ONCE, retrieved.isViewOnce() ? 1 : 0);
|
||||
contentValues.put(IS_STORY, retrieved.isStory() ? 1 : 0);
|
||||
contentValues.put(PARENT_STORY_ID, retrieved.getParentStoryId() != null ? retrieved.getParentStoryId().getId() : 0);
|
||||
contentValues.put(PARENT_STORY_ID, retrieved.getParentStoryId() != null ? retrieved.getParentStoryId().serialize() : 0);
|
||||
contentValues.put(READ, retrieved.isExpirationUpdate() ? 1 : 0);
|
||||
contentValues.put(UNIDENTIFIED, retrieved.isUnidentified());
|
||||
contentValues.put(SERVER_GUID, retrieved.getServerGuid());
|
||||
@@ -1785,7 +1786,7 @@ public class MmsDatabase extends MessageDatabase {
|
||||
contentValues.put(DELIVERY_RECEIPT_COUNT, Stream.of(earlyDeliveryReceipts.values()).mapToLong(EarlyReceiptCache.Receipt::getCount).sum());
|
||||
contentValues.put(RECEIPT_TIMESTAMP, Stream.of(earlyDeliveryReceipts.values()).mapToLong(EarlyReceiptCache.Receipt::getTimestamp).max().orElse(-1));
|
||||
contentValues.put(IS_STORY, message.isStory() ? 1 : 0);
|
||||
contentValues.put(PARENT_STORY_ID, message.getParentStoryId() != null ? message.getParentStoryId().getId() : 0);
|
||||
contentValues.put(PARENT_STORY_ID, message.getParentStoryId() != null ? message.getParentStoryId().serialize() : 0);
|
||||
|
||||
if (message.getRecipient().isSelf() && hasAudioAttachment(message.getAttachments())) {
|
||||
contentValues.put(VIEWED_RECEIPT_COUNT, 1L);
|
||||
|
||||
@@ -118,7 +118,7 @@ public class MmsSmsDatabase extends Database {
|
||||
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + SmsDatabase.TYPE + " NOT IN (" + SmsDatabase.Types.PROFILE_CHANGE_TYPE + ", " + SmsDatabase.Types.GV1_MIGRATION_TYPE + ", " + SmsDatabase.Types.CHANGE_NUMBER_TYPE + ", " + SmsDatabase.Types.BOOST_REQUEST_TYPE + ") AND " + SmsDatabase.TYPE + " & " + GROUP_V2_LEAVE_BITS + " != " + GROUP_V2_LEAVE_BITS + " " +
|
||||
"UNION ALL " +
|
||||
"SELECT " + MmsSmsColumns.ID + ", 1 AS " + TRANSPORT + ", " + MmsDatabase.MESSAGE_BOX + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + MmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + MmsDatabase.TABLE_NAME + " " +
|
||||
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + MmsDatabase.MESSAGE_BOX + " & " + GROUP_V2_LEAVE_BITS + " != " + GROUP_V2_LEAVE_BITS + " AND " + MmsDatabase.IS_STORY + " = 0 AND " + MmsDatabase.PARENT_STORY_ID + " = 0 " +
|
||||
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + MmsDatabase.MESSAGE_BOX + " & " + GROUP_V2_LEAVE_BITS + " != " + GROUP_V2_LEAVE_BITS + " AND " + MmsDatabase.IS_STORY + " = 0 AND " + MmsDatabase.PARENT_STORY_ID + " <= 0 " +
|
||||
"ORDER BY " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " DESC " +
|
||||
"LIMIT 1";
|
||||
|
||||
@@ -202,7 +202,7 @@ public class MmsSmsDatabase extends Database {
|
||||
public Cursor getConversation(long threadId, long offset, long limit) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
|
||||
String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " DESC";
|
||||
String selection = MmsSmsColumns.THREAD_ID + " = " + threadId + " AND " + MmsDatabase.IS_STORY + " = 0 AND " + MmsDatabase.PARENT_STORY_ID + " = 0";
|
||||
String selection = MmsSmsColumns.THREAD_ID + " = " + threadId + " AND " + MmsDatabase.IS_STORY + " = 0 AND " + MmsDatabase.PARENT_STORY_ID + " <= 0";
|
||||
String limitStr = limit > 0 || offset > 0 ? offset + ", " + limit : null;
|
||||
String query = buildQuery(PROJECTION, selection, order, limitStr, false);
|
||||
|
||||
@@ -264,19 +264,16 @@ public class MmsSmsDatabase extends Database {
|
||||
}
|
||||
|
||||
String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " ASC";
|
||||
String selection = MmsSmsColumns.NOTIFIED + " = 0 AND (" + MmsSmsColumns.READ + " = 0 OR " + MmsSmsColumns.REACTIONS_UNREAD + " = 1" + (stickyQuery.length() > 0 ? " OR (" + stickyQuery.toString() + ")" : "") + ")";
|
||||
String selection = MmsSmsColumns.NOTIFIED + " = 0 AND " + MmsDatabase.IS_STORY + " = 0 AND " + MmsDatabase.PARENT_STORY_ID + " <= 0 AND (" + MmsSmsColumns.READ + " = 0 OR " + MmsSmsColumns.REACTIONS_UNREAD + " = 1" + (stickyQuery.length() > 0 ? " OR (" + stickyQuery.toString() + ")" : "") + ")";
|
||||
|
||||
return queryTables(PROJECTION, selection, order, null);
|
||||
}
|
||||
|
||||
public int getUnreadCount(long threadId) {
|
||||
String selection = MmsSmsColumns.READ + " = 0 AND " + MmsSmsColumns.THREAD_ID + " = " + threadId;
|
||||
Cursor cursor = queryTables(PROJECTION, selection, null, null);
|
||||
String selection = MmsSmsColumns.READ + " = 0 AND " + MmsDatabase.IS_STORY + " = 0 AND " + MmsSmsColumns.THREAD_ID + " = " + threadId + " AND " + MmsDatabase.PARENT_STORY_ID + " <= 0";
|
||||
|
||||
try {
|
||||
try (Cursor cursor = queryTables(PROJECTION, selection, null, null)) {
|
||||
return cursor != null ? cursor.getCount() : 0;
|
||||
} finally {
|
||||
if (cursor != null) cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.thoughtcrime.securesms.database.model
|
||||
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
* Abstract representation of a message id for a story.
|
||||
*
|
||||
* At the database layer, the sign of the id is dependant on whether a reply is meant for
|
||||
* a group thread or a direct reply. This class facilitates that, while still allowing for
|
||||
* normal behaviour elsewhere.
|
||||
*/
|
||||
sealed class ParentStoryId(protected val id: Long) {
|
||||
abstract fun serialize(): Long
|
||||
|
||||
fun asMessageId(): MessageId = MessageId(abs(id), true)
|
||||
|
||||
/**
|
||||
* A parent story who's child should be displayed in a group reply thread.
|
||||
*/
|
||||
class GroupReply(id: Long) : ParentStoryId(id) {
|
||||
override fun serialize(): Long = abs(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* A parent story who's child should be displayed in a 1:1 conversation.
|
||||
*/
|
||||
class DirectReply(id: Long) : ParentStoryId(id) {
|
||||
override fun serialize(): Long = -abs(id)
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Takes a long stored in the database and converts it to an appropriate subclass of ParentStoryId.
|
||||
* If the passed value is 0L, null is returned.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun deserialize(id: Long): ParentStoryId? {
|
||||
return when {
|
||||
id > 0L -> GroupReply(id)
|
||||
id < 0L -> DirectReply(id)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user