mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-22 18:00:02 +01:00
Add support for mark as unread.
This commit is contained in:
@@ -56,12 +56,14 @@ import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -92,17 +94,27 @@ public class ThreadDatabase extends Database {
|
||||
public static final String LAST_SEEN = "last_seen";
|
||||
public static final String HAS_SENT = "has_sent";
|
||||
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" +
|
||||
ID + " INTEGER PRIMARY KEY, " + DATE + " INTEGER DEFAULT 0, " +
|
||||
MESSAGE_COUNT + " INTEGER DEFAULT 0, " + RECIPIENT_ID + " INTEGER, " + SNIPPET + " TEXT, " +
|
||||
SNIPPET_CHARSET + " INTEGER DEFAULT 0, " + READ + " INTEGER DEFAULT 1, " +
|
||||
TYPE + " INTEGER DEFAULT 0, " + ERROR + " INTEGER DEFAULT 0, " +
|
||||
SNIPPET_TYPE + " INTEGER DEFAULT 0, " + SNIPPET_URI + " TEXT DEFAULT NULL, " +
|
||||
SNIPPET_CONTENT_TYPE + " TEXT DEFAULT NULL, " + SNIPPET_EXTRAS + " TEXT DEFAULT NULL, " +
|
||||
ARCHIVED + " INTEGER DEFAULT 0, " + STATUS + " INTEGER DEFAULT 0, " +
|
||||
DELIVERY_RECEIPT_COUNT + " INTEGER DEFAULT 0, " + EXPIRES_IN + " INTEGER DEFAULT 0, " +
|
||||
LAST_SEEN + " INTEGER DEFAULT 0, " + HAS_SENT + " INTEGER DEFAULT 0, " +
|
||||
READ_RECEIPT_COUNT + " INTEGER DEFAULT 0, " + UNREAD_COUNT + " INTEGER DEFAULT 0);";
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
DATE + " INTEGER DEFAULT 0, " +
|
||||
MESSAGE_COUNT + " INTEGER DEFAULT 0, " +
|
||||
RECIPIENT_ID + " INTEGER, " +
|
||||
SNIPPET + " TEXT, " +
|
||||
SNIPPET_CHARSET + " INTEGER DEFAULT 0, " +
|
||||
READ + " INTEGER DEFAULT " + ReadStatus.READ.serialize() + ", " +
|
||||
TYPE + " INTEGER DEFAULT 0, " +
|
||||
ERROR + " INTEGER DEFAULT 0, " +
|
||||
SNIPPET_TYPE + " INTEGER DEFAULT 0, " +
|
||||
SNIPPET_URI + " TEXT DEFAULT NULL, " +
|
||||
SNIPPET_CONTENT_TYPE + " TEXT DEFAULT NULL, " +
|
||||
SNIPPET_EXTRAS + " TEXT DEFAULT NULL, " +
|
||||
ARCHIVED + " INTEGER DEFAULT 0, " +
|
||||
STATUS + " INTEGER DEFAULT 0, " +
|
||||
DELIVERY_RECEIPT_COUNT + " INTEGER DEFAULT 0, " +
|
||||
EXPIRES_IN + " INTEGER DEFAULT 0, " +
|
||||
LAST_SEEN + " INTEGER DEFAULT 0, " +
|
||||
HAS_SENT + " INTEGER DEFAULT 0, " +
|
||||
READ_RECEIPT_COUNT + " INTEGER DEFAULT 0, " +
|
||||
UNREAD_COUNT + " INTEGER DEFAULT 0);";
|
||||
|
||||
public static final String[] CREATE_INDEXS = {
|
||||
"CREATE INDEX IF NOT EXISTS thread_recipient_ids_index ON " + TABLE_NAME + " (" + RECIPIENT_ID + ");",
|
||||
@@ -280,7 +292,7 @@ public class ThreadDatabase extends Database {
|
||||
public List<MarkedMessageInfo> setAllThreadsRead() {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(READ, 1);
|
||||
contentValues.put(READ, ReadStatus.READ.serialize());
|
||||
contentValues.put(UNREAD_COUNT, 0);
|
||||
|
||||
db.update(TABLE_NAME, contentValues, null, null);
|
||||
@@ -310,32 +322,69 @@ public class ThreadDatabase extends Database {
|
||||
}
|
||||
|
||||
public List<MarkedMessageInfo> setRead(long threadId, boolean lastSeen) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(READ, 1);
|
||||
contentValues.put(UNREAD_COUNT, 0);
|
||||
|
||||
if (lastSeen) {
|
||||
contentValues.put(LAST_SEEN, System.currentTimeMillis());
|
||||
}
|
||||
return setRead(Collections.singletonList(threadId), lastSeen);
|
||||
}
|
||||
|
||||
public List<MarkedMessageInfo> setRead(Collection<Long> threadIds, boolean lastSeen) {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
|
||||
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {threadId+""});
|
||||
List<MarkedMessageInfo> smsRecords = new LinkedList<>();
|
||||
List<MarkedMessageInfo> mmsRecords = new LinkedList<>();
|
||||
|
||||
final List<MarkedMessageInfo> smsRecords = DatabaseFactory.getSmsDatabase(context).setMessagesRead(threadId);
|
||||
final List<MarkedMessageInfo> mmsRecords = DatabaseFactory.getMmsDatabase(context).setMessagesRead(threadId);
|
||||
db.beginTransaction();
|
||||
|
||||
DatabaseFactory.getSmsDatabase(context).setReactionsSeen(threadId);
|
||||
DatabaseFactory.getMmsDatabase(context).setReactionsSeen(threadId);
|
||||
try {
|
||||
ContentValues contentValues = new ContentValues(2);
|
||||
contentValues.put(READ, ReadStatus.READ.serialize());
|
||||
contentValues.put(UNREAD_COUNT, 0);
|
||||
|
||||
if (lastSeen) {
|
||||
contentValues.put(LAST_SEEN, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
for (long threadId : threadIds) {
|
||||
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[]{threadId + ""});
|
||||
|
||||
smsRecords.addAll(DatabaseFactory.getSmsDatabase(context).setMessagesRead(threadId));
|
||||
mmsRecords.addAll(DatabaseFactory.getMmsDatabase(context).setMessagesRead(threadId));
|
||||
|
||||
DatabaseFactory.getSmsDatabase(context).setReactionsSeen(threadId);
|
||||
DatabaseFactory.getMmsDatabase(context).setReactionsSeen(threadId);
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
notifyConversationListListeners();
|
||||
|
||||
return Util.concatenatedList(smsRecords, mmsRecords);
|
||||
}
|
||||
|
||||
public void setForcedUnread(@NonNull Collection<Long> threadIds) {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
|
||||
db.beginTransaction();
|
||||
try {
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(READ, ReadStatus.FORCED_UNREAD.serialize());
|
||||
|
||||
for (long threadId : threadIds) {
|
||||
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] { String.valueOf(threadId) });
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
|
||||
|
||||
public void incrementUnread(long threadId, int amount) {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
db.execSQL("UPDATE " + TABLE_NAME + " SET " + READ + " = 0, " +
|
||||
db.execSQL("UPDATE " + TABLE_NAME + " SET " + READ + " = " + ReadStatus.UNREAD.serialize() + ", " +
|
||||
UNREAD_COUNT + " = " + UNREAD_COUNT + " + ? WHERE " + ID + " = ?",
|
||||
new String[] {String.valueOf(amount),
|
||||
String.valueOf(threadId)});
|
||||
@@ -882,6 +931,7 @@ public class ThreadDatabase extends Database {
|
||||
.setContentType(cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET_CONTENT_TYPE)))
|
||||
.setCount(cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.MESSAGE_COUNT)))
|
||||
.setUnreadCount(cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.UNREAD_COUNT)))
|
||||
.setForcedUnread(cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.READ)) == ReadStatus.FORCED_UNREAD.serialize())
|
||||
.setExtra(extra)
|
||||
.build();
|
||||
}
|
||||
@@ -990,4 +1040,27 @@ public class ThreadDatabase extends Database {
|
||||
return groupAddedBy;
|
||||
}
|
||||
}
|
||||
|
||||
private enum ReadStatus {
|
||||
READ(1), UNREAD(0), FORCED_UNREAD(2);
|
||||
|
||||
private final int value;
|
||||
|
||||
ReadStatus(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static ReadStatus deserialize(int value) {
|
||||
for (ReadStatus status : ReadStatus.values()) {
|
||||
if (status.value == value) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("No matching status for value " + value);
|
||||
}
|
||||
|
||||
public int serialize() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,14 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase.Extra;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.whispersystems.libsignal.util.guava.Preconditions;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents an entry in the {@link org.thoughtcrime.securesms.database.ThreadDatabase}.
|
||||
*/
|
||||
@@ -47,6 +50,7 @@ public final class ThreadRecord {
|
||||
private final Extra extra;
|
||||
private final long count;
|
||||
private final int unreadCount;
|
||||
private final boolean forcedUnread;
|
||||
private final int distributionType;
|
||||
private final boolean archived;
|
||||
private final long expiresIn;
|
||||
@@ -66,6 +70,7 @@ public final class ThreadRecord {
|
||||
this.extra = builder.extra;
|
||||
this.count = builder.count;
|
||||
this.unreadCount = builder.unreadCount;
|
||||
this.forcedUnread = builder.forcedUnread;
|
||||
this.distributionType = builder.distributionType;
|
||||
this.archived = builder.archived;
|
||||
this.expiresIn = builder.expiresIn;
|
||||
@@ -104,6 +109,14 @@ public final class ThreadRecord {
|
||||
return unreadCount;
|
||||
}
|
||||
|
||||
public boolean isForcedUnread() {
|
||||
return forcedUnread;
|
||||
}
|
||||
|
||||
public boolean isRead() {
|
||||
return unreadCount == 0 && !forcedUnread;
|
||||
}
|
||||
|
||||
public long getDate() {
|
||||
return date;
|
||||
}
|
||||
@@ -188,6 +201,7 @@ public final class ThreadRecord {
|
||||
private Extra extra;
|
||||
private long count;
|
||||
private int unreadCount;
|
||||
private boolean forcedUnread;
|
||||
private int distributionType;
|
||||
private boolean archived;
|
||||
private long expiresIn;
|
||||
@@ -262,6 +276,11 @@ public final class ThreadRecord {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setForcedUnread(boolean forcedUnread) {
|
||||
this.forcedUnread = forcedUnread;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDistributionType(int distributionType) {
|
||||
this.distributionType = distributionType;
|
||||
return this;
|
||||
@@ -283,10 +302,12 @@ public final class ThreadRecord {
|
||||
}
|
||||
|
||||
public ThreadRecord build() {
|
||||
Preconditions.checkArgument(threadId > 0);
|
||||
Preconditions.checkArgument(date > 0);
|
||||
Preconditions.checkNotNull(body);
|
||||
Preconditions.checkNotNull(recipient);
|
||||
if (distributionType == ThreadDatabase.DistributionTypes.CONVERSATION) {
|
||||
Preconditions.checkArgument(threadId > 0);
|
||||
Preconditions.checkArgument(date > 0);
|
||||
Preconditions.checkNotNull(body);
|
||||
Preconditions.checkNotNull(recipient);
|
||||
}
|
||||
return new ThreadRecord(this);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user