Join group information into conversation list query

// FREEBIE
This commit is contained in:
Moxie Marlinspike
2017-08-07 16:47:38 -07:00
parent 159fdb317f
commit da94fd5f9e
11 changed files with 163 additions and 104 deletions

View File

@@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.database;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@@ -11,12 +10,17 @@ import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
import java.io.IOException;
@@ -32,9 +36,9 @@ public class GroupDatabase extends Database {
private static final String TAG = GroupDatabase.class.getSimpleName();
private static final String TABLE_NAME = "groups";
static final String TABLE_NAME = "groups";
private static final String ID = "_id";
private static final String GROUP_ID = "group_id";
static final String GROUP_ID = "group_id";
private static final String TITLE = "title";
private static final String MEMBERS = "members";
private static final String AVATAR = "avatar";
@@ -67,21 +71,33 @@ public class GroupDatabase extends Database {
"CREATE UNIQUE INDEX IF NOT EXISTS group_id_index ON " + TABLE_NAME + " (" + GROUP_ID + ");",
};
private static final String[] GROUP_PROJECTION = {
GROUP_ID, TITLE, MEMBERS, AVATAR, AVATAR_ID, AVATAR_KEY, AVATAR_CONTENT_TYPE, AVATAR_RELAY, AVATAR_DIGEST,
TIMESTAMP, ACTIVE, MMS
};
static final List<String> TYPED_GROUP_PROJECTION = Stream.of(GROUP_PROJECTION).map(columnName -> TABLE_NAME + "." + columnName).toList();
public GroupDatabase(Context context, SQLiteOpenHelper databaseHelper) {
super(context, databaseHelper);
}
public @Nullable GroupRecord getGroup(String groupId) {
@SuppressLint("Recycle")
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, GROUP_ID + " = ?",
new String[] {groupId},
null, null, null);
public Optional<GroupRecord> getGroup(String groupId) {
try (Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, GROUP_ID + " = ?",
new String[] {groupId},
null, null, null))
{
if (cursor != null && cursor.moveToNext()) {
return getGroup(cursor);
}
Reader reader = new Reader(cursor);
GroupRecord record = reader.getNext();
return Optional.absent();
}
}
reader.close();
return record;
Optional<GroupRecord> getGroup(Cursor cursor) {
Reader reader = new Reader(cursor);
return Optional.fromNullable(reader.getCurrent());
}
public boolean isUnknownGroup(String groupId) {
@@ -251,8 +267,8 @@ public class GroupDatabase extends Database {
}
public boolean isActive(String groupId) {
GroupRecord record = getGroup(groupId);
return record != null && record.isActive();
Optional<GroupRecord> record = getGroup(groupId);
return record.isPresent() && record.get().isActive();
}
public void setActive(String groupId, boolean active) {
@@ -291,6 +307,14 @@ public class GroupDatabase extends Database {
return null;
}
return getCurrent();
}
public @Nullable GroupRecord getCurrent() {
if (cursor == null || cursor.getString(cursor.getColumnIndexOrThrow(GROUP_ID)) == null) {
return null;
}
return new GroupRecord(cursor.getString(cursor.getColumnIndexOrThrow(GROUP_ID)),
cursor.getString(cursor.getColumnIndexOrThrow(TITLE)),
cursor.getString(cursor.getColumnIndexOrThrow(MEMBERS)),
@@ -330,7 +354,6 @@ public class GroupDatabase extends Database {
{
this.id = id;
this.title = title;
this.members = Address.fromSerializedList(members, ',');
this.avatar = avatar;
this.avatarId = avatarId;
this.avatarKey = avatarKey;
@@ -339,6 +362,9 @@ public class GroupDatabase extends Database {
this.relay = relay;
this.active = active;
this.mms = mms;
if (!TextUtils.isEmpty(members)) this.members = Address.fromSerializedList(members, ',');
else this.members = new LinkedList<>();
}
public byte[] getId() {

View File

@@ -30,7 +30,7 @@ public class RecipientPreferenceDatabase extends Database {
static final String TABLE_NAME = "recipient_preferences";
private static final String ID = "_id";
private static final String ADDRESS = "recipient_ids";
static final String ADDRESS = "recipient_ids";
private static final String BLOCK = "block";
private static final String NOTIFICATION = "notification";
private static final String VIBRATE = "vibrate";
@@ -110,7 +110,7 @@ public class RecipientPreferenceDatabase extends Database {
cursor = database.query(TABLE_NAME, null, ADDRESS + " = ?", new String[] {address.serialize()}, null, null, null);
if (cursor != null && cursor.moveToNext()) {
return Optional.of(getRecipientPreferences(cursor));
return getRecipientPreferences(cursor);
}
return Optional.absent();
@@ -119,7 +119,7 @@ public class RecipientPreferenceDatabase extends Database {
}
}
RecipientsPreferences getRecipientPreferences(@NonNull Cursor cursor) {
Optional<RecipientsPreferences> getRecipientPreferences(@NonNull Cursor cursor) {
boolean blocked = cursor.getInt(cursor.getColumnIndexOrThrow(BLOCK)) == 1;
String notification = cursor.getString(cursor.getColumnIndexOrThrow(NOTIFICATION));
int vibrateState = cursor.getInt(cursor.getColumnIndexOrThrow(VIBRATE));
@@ -141,11 +141,11 @@ public class RecipientPreferenceDatabase extends Database {
color = null;
}
return new RecipientsPreferences(blocked, muteUntil,
VibrateState.fromId(vibrateState),
notificationUri, color, seenInviteReminder,
defaultSubscriptionId, expireMessages, registered,
systemDisplayname);
return Optional.of(new RecipientsPreferences(blocked, muteUntil,
VibrateState.fromId(vibrateState),
notificationUri, color, seenInviteReminder,
defaultSubscriptionId, expireMessages, registered,
systemDisplayname));
}
public void setColor(Recipient recipient, MaterialColor color) {

View File

@@ -31,6 +31,7 @@ import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.crypto.MasterCipher;
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
import org.thoughtcrime.securesms.database.model.DisplayRecord;
@@ -44,6 +45,7 @@ import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.util.DelimiterUtil;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.InvalidMessageException;
import org.whispersystems.libsignal.util.guava.Optional;
import java.util.LinkedList;
import java.util.List;
@@ -95,9 +97,10 @@ public class ThreadDatabase extends Database {
.map(columnName -> TABLE_NAME + "." + columnName)
.toList();
private static final List<String> COMBINED_THREAD_RECIPIENT_PROJECTION = Stream.concat(Stream.of(TYPED_THREAD_PROJECTION),
Stream.of(RecipientPreferenceDatabase.TYPED_RECIPIENT_PROJECTION))
.toList();
private static final List<String> COMBINED_THREAD_RECIPIENT_GROUP_PROJECTION = Stream.concat(Stream.concat(Stream.of(TYPED_THREAD_PROJECTION),
Stream.of(RecipientPreferenceDatabase.TYPED_RECIPIENT_PROJECTION)),
Stream.of(GroupDatabase.TYPED_GROUP_PROJECTION))
.toList();
public ThreadDatabase(Context context, SQLiteOpenHelper databaseHelper) {
super(context, databaseHelper);
@@ -340,11 +343,13 @@ public class ThreadDatabase extends Database {
}
private Cursor getConversationList(String archived) {
String projection = Util.join(COMBINED_THREAD_RECIPIENT_PROJECTION, ",");
String projection = Util.join(COMBINED_THREAD_RECIPIENT_GROUP_PROJECTION, ",");
SQLiteDatabase db = databaseHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT " + projection + " FROM " + TABLE_NAME +
" LEFT OUTER JOIN " + RecipientPreferenceDatabase.TABLE_NAME +
" ON " + TABLE_NAME + "." + ADDRESS + " = " + RecipientPreferenceDatabase.TABLE_NAME + "." + ADDRESS +
" ON " + TABLE_NAME + "." + ADDRESS + " = " + RecipientPreferenceDatabase.TABLE_NAME + "." + RecipientPreferenceDatabase.ADDRESS +
" LEFT OUTER JOIN " + GroupDatabase.TABLE_NAME +
" ON " + TABLE_NAME + "." + ADDRESS + " = " + GroupDatabase.TABLE_NAME + "." + GroupDatabase.GROUP_ID +
" WHERE " + ARCHIVED + " = ? AND " + MESSAGE_COUNT + " != 0" +
" ORDER BY " + TABLE_NAME + "." + DATE + " DESC",
new String[] {archived});
@@ -356,7 +361,7 @@ public class ThreadDatabase extends Database {
public Cursor getDirectShareList() {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
String projection = Util.join(COMBINED_THREAD_RECIPIENT_PROJECTION, ",");
String projection = Util.join(COMBINED_THREAD_RECIPIENT_GROUP_PROJECTION, ",");
return db.rawQuery("SELECT " + projection + " FROM " + TABLE_NAME +
" LEFT OUTER JOIN " + RecipientPreferenceDatabase.TABLE_NAME +
@@ -601,10 +606,11 @@ public class ThreadDatabase extends Database {
}
public ThreadRecord getCurrent() {
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.ID));
Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.ADDRESS)));
RecipientsPreferences preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientPreferences(cursor);
Recipient recipient = RecipientFactory.getRecipientFor(context, address, preferences, true);
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.ID));
Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.ADDRESS)));
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientPreferences(cursor);
Optional<GroupRecord> groupRecord = DatabaseFactory.getGroupDatabase(context).getGroup(cursor);
Recipient recipient = RecipientFactory.getRecipientFor(context, address, preferences, groupRecord, true);
DisplayRecord.Body body = getPlaintextBody(cursor);
long date = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.DATE));