mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-22 01:40:07 +01:00
Add ability to pin up to 4 conversations.
This commit is contained in:
committed by
Greyson Parrelli
parent
9892c4392e
commit
d63e5165eb
@@ -31,6 +31,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import net.sqlcipher.database.SQLiteDatabase;
|
||||
|
||||
import org.jsoup.helper.StringUtil;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedMember;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
@@ -96,6 +97,7 @@ public class ThreadDatabase extends Database {
|
||||
public static final String LAST_SEEN = "last_seen";
|
||||
public static final String HAS_SENT = "has_sent";
|
||||
private static final String LAST_SCROLLED = "last_scrolled";
|
||||
private static final String PINNED = "pinned";
|
||||
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
DATE + " INTEGER DEFAULT 0, " +
|
||||
@@ -118,16 +120,18 @@ public class ThreadDatabase extends Database {
|
||||
HAS_SENT + " INTEGER DEFAULT 0, " +
|
||||
READ_RECEIPT_COUNT + " INTEGER DEFAULT 0, " +
|
||||
UNREAD_COUNT + " INTEGER DEFAULT 0, " +
|
||||
LAST_SCROLLED + " INTEGER DEFAULT 0);";
|
||||
LAST_SCROLLED + " INTEGER DEFAULT 0, " +
|
||||
PINNED + " INTEGER DEFAULT 0);";
|
||||
|
||||
public static final String[] CREATE_INDEXS = {
|
||||
"CREATE INDEX IF NOT EXISTS thread_recipient_ids_index ON " + TABLE_NAME + " (" + RECIPIENT_ID + ");",
|
||||
"CREATE INDEX IF NOT EXISTS archived_count_index ON " + TABLE_NAME + " (" + ARCHIVED + ", " + MESSAGE_COUNT + ");",
|
||||
"CREATE INDEX IF NOT EXISTS thread_pinned_index ON " + TABLE_NAME + " (" + PINNED + ");",
|
||||
};
|
||||
|
||||
private static final String[] THREAD_PROJECTION = {
|
||||
ID, DATE, MESSAGE_COUNT, RECIPIENT_ID, SNIPPET, SNIPPET_CHARSET, READ, UNREAD_COUNT, TYPE, ERROR, SNIPPET_TYPE,
|
||||
SNIPPET_URI, SNIPPET_CONTENT_TYPE, SNIPPET_EXTRAS, ARCHIVED, STATUS, DELIVERY_RECEIPT_COUNT, EXPIRES_IN, LAST_SEEN, READ_RECEIPT_COUNT, LAST_SCROLLED
|
||||
SNIPPET_URI, SNIPPET_CONTENT_TYPE, SNIPPET_EXTRAS, ARCHIVED, STATUS, DELIVERY_RECEIPT_COUNT, EXPIRES_IN, LAST_SEEN, READ_RECEIPT_COUNT, LAST_SCROLLED, PINNED
|
||||
};
|
||||
|
||||
private static final List<String> TYPED_THREAD_PROJECTION = Stream.of(THREAD_PROJECTION)
|
||||
@@ -579,8 +583,12 @@ public class ThreadDatabase extends Database {
|
||||
return positions;
|
||||
}
|
||||
|
||||
public Cursor getConversationList(long offset, long limit) {
|
||||
return getConversationList("0", offset, limit);
|
||||
public Cursor getPinnedConversationList(long offset, long limit) {
|
||||
return getUnarchivedConversationList("1", offset, limit);
|
||||
}
|
||||
|
||||
public Cursor getUnpinnedConversationList(long offset, long limit) {
|
||||
return getUnarchivedConversationList("0", offset, limit);
|
||||
}
|
||||
|
||||
public Cursor getArchivedConversationList(long offset, long limit) {
|
||||
@@ -591,6 +599,16 @@ public class ThreadDatabase extends Database {
|
||||
return getConversationList(archived, 0, 0);
|
||||
}
|
||||
|
||||
private Cursor getUnarchivedConversationList(@NonNull String pinned, long offset, long limit) {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
String query = createQuery(ARCHIVED + " = 0 AND " + MESSAGE_COUNT + " != 0 AND " + PINNED + " = ?", offset, limit);
|
||||
Cursor cursor = db.rawQuery(query, new String[]{pinned});
|
||||
|
||||
setNotifyConversationListListeners(cursor);
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
private Cursor getConversationList(@NonNull String archived, long offset, long limit) {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
String query = createQuery(ARCHIVED + " = ? AND " + MESSAGE_COUNT + " != 0", offset, limit);
|
||||
@@ -601,19 +619,19 @@ public class ThreadDatabase extends Database {
|
||||
return cursor;
|
||||
}
|
||||
|
||||
public int getUnarchivedConversationListCount() {
|
||||
return getConversationListCount(false);
|
||||
public int getPinnedConversationListCount() {
|
||||
return getUnarchivedConversationListCount(true);
|
||||
}
|
||||
|
||||
public int getUnpinnedConversationListCount() {
|
||||
return getUnarchivedConversationListCount(false);
|
||||
}
|
||||
|
||||
public int getArchivedConversationListCount() {
|
||||
return getConversationListCount(true);
|
||||
}
|
||||
|
||||
private int getConversationListCount(boolean archived) {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
String[] columns = new String[] { "COUNT(*)" };
|
||||
String query = ARCHIVED + " = ? AND " + MESSAGE_COUNT + " != 0";
|
||||
String[] args = new String[] { archived ? "1" : "0" };
|
||||
String[] args = new String[] {"1"};
|
||||
|
||||
try (Cursor cursor = db.query(TABLE_NAME, columns, query, args, null, null, null)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
@@ -624,6 +642,46 @@ public class ThreadDatabase extends Database {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int getUnarchivedConversationListCount(boolean pinned) {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
String[] columns = new String[] { "COUNT(*)" };
|
||||
String query = ARCHIVED + " = 0 AND " + MESSAGE_COUNT + " != 0 AND " + PINNED + " = ?";
|
||||
String[] args = new String[] { pinned ? "1" : "0" };
|
||||
|
||||
try (Cursor cursor = db.query(TABLE_NAME, columns, query, args, null, null, null)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
return cursor.getInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void pinConversations(@NonNull Set<Long> threadIds) {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
String placeholders = StringUtil.join(Stream.of(threadIds).map(unused -> "?").toList(), ",");
|
||||
String selection = ID + " IN (" + placeholders + ")";
|
||||
|
||||
contentValues.put(PINNED, 1);
|
||||
|
||||
db.update(TABLE_NAME, contentValues, selection, SqlUtil.buildArgs(Stream.of(threadIds).toArray()));
|
||||
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
|
||||
public void unpinConversations(@NonNull Set<Long> threadIds) {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
String placeholders = StringUtil.join(Stream.of(threadIds).map(unused -> "?").toList(), ",");
|
||||
String selection = ID + " IN (" + placeholders + ")";
|
||||
|
||||
contentValues.put(PINNED, 0);
|
||||
|
||||
db.update(TABLE_NAME, contentValues, selection, SqlUtil.buildArgs(Stream.of(threadIds).toArray()));
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
|
||||
public void archiveConversation(long threadId) {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
@@ -1122,6 +1180,7 @@ public class ThreadDatabase extends Database {
|
||||
.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())
|
||||
.setPinned(CursorUtil.requireBoolean(cursor, ThreadDatabase.PINNED))
|
||||
.setExtra(extra)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -141,8 +141,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
private static final int BORDERLESS = 66;
|
||||
private static final int REMAPPED_RECORDS = 67;
|
||||
private static final int MENTIONS = 68;
|
||||
private static final int PINNED_CONVERSATIONS = 69;
|
||||
|
||||
private static final int DATABASE_VERSION = 68;
|
||||
private static final int DATABASE_VERSION = 69;
|
||||
private static final String DATABASE_NAME = "signal.db";
|
||||
|
||||
private final Context context;
|
||||
@@ -991,6 +992,11 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
db.execSQL("ALTER TABLE recipient ADD COLUMN mention_setting INTEGER DEFAULT 0");
|
||||
}
|
||||
|
||||
if (oldVersion < PINNED_CONVERSATIONS) {
|
||||
db.execSQL("ALTER TABLE thread ADD COLUMN pinned INTEGER DEFAULT 0");
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS thread_pinned_index ON thread (pinned)");
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
|
||||
@@ -55,6 +55,7 @@ public final class ThreadRecord {
|
||||
private final boolean archived;
|
||||
private final long expiresIn;
|
||||
private final long lastSeen;
|
||||
private final boolean isPinned;
|
||||
|
||||
private ThreadRecord(@NonNull Builder builder) {
|
||||
this.threadId = builder.threadId;
|
||||
@@ -75,6 +76,7 @@ public final class ThreadRecord {
|
||||
this.archived = builder.archived;
|
||||
this.expiresIn = builder.expiresIn;
|
||||
this.lastSeen = builder.lastSeen;
|
||||
this.isPinned = builder.isPinned;
|
||||
}
|
||||
|
||||
public long getThreadId() {
|
||||
@@ -187,6 +189,10 @@ public final class ThreadRecord {
|
||||
else return true;
|
||||
}
|
||||
|
||||
public boolean isPinned() {
|
||||
return isPinned;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@@ -205,6 +211,7 @@ public final class ThreadRecord {
|
||||
archived == that.archived &&
|
||||
expiresIn == that.expiresIn &&
|
||||
lastSeen == that.lastSeen &&
|
||||
isPinned == that.isPinned &&
|
||||
body.equals(that.body) &&
|
||||
recipient.equals(that.recipient) &&
|
||||
Objects.equals(snippetUri, that.snippetUri) &&
|
||||
@@ -231,7 +238,8 @@ public final class ThreadRecord {
|
||||
distributionType,
|
||||
archived,
|
||||
expiresIn,
|
||||
lastSeen);
|
||||
lastSeen,
|
||||
isPinned);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
@@ -253,6 +261,7 @@ public final class ThreadRecord {
|
||||
private boolean archived;
|
||||
private long expiresIn;
|
||||
private long lastSeen;
|
||||
private boolean isPinned;
|
||||
|
||||
public Builder(long threadId) {
|
||||
this.threadId = threadId;
|
||||
@@ -348,6 +357,11 @@ public final class ThreadRecord {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPinned(boolean isPinned) {
|
||||
this.isPinned = isPinned;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ThreadRecord build() {
|
||||
if (distributionType == ThreadDatabase.DistributionTypes.CONVERSATION) {
|
||||
Preconditions.checkArgument(threadId > 0);
|
||||
|
||||
Reference in New Issue
Block a user