mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-23 08:27:30 +00:00
Join recipient preferences into thread query for faster lookup
// FREEBIE
This commit is contained in:
parent
375207f073
commit
a02f223a96
10
build.gradle
10
build.gradle
@ -10,11 +10,13 @@ buildscript {
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.3.0'
|
||||
classpath files('libs/gradle-witness.jar')
|
||||
classpath 'me.tatarka:gradle-retrolambda:3.7.0'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'witness'
|
||||
apply plugin: 'me.tatarka.retrolambda'
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
@ -99,6 +101,8 @@ dependencies {
|
||||
exclude group: 'com.squareup.okhttp', module: 'okhttp'
|
||||
exclude group: 'com.squareup.okhttp', module: 'okhttp-urlconnection'
|
||||
}
|
||||
compile 'com.annimon:stream:1.1.8'
|
||||
|
||||
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile 'org.assertj:assertj-core:1.7.1'
|
||||
@ -160,6 +164,7 @@ dependencyVerification {
|
||||
'cn.carbswang.android:NumberPickerView:18b3c316d62c7c277978a8d4ed57a5b8f4e943762264960f579a8a549c756729',
|
||||
'com.tomergoldst.android:tooltips:4c56697dd1ad64b8066535c61f961a6d901e7ae5d97ae27084ba40ad620349b6',
|
||||
'com.klinkerapps:android-smsmms:e7c3328a0f3a8dd44daa8129de4e99996f3057a4546e47891b036b81e0ebf1d1',
|
||||
'com.annimon:stream:5da6e2e3e0551d61a3ea7014f04312276549e3dd739cf637996e4cf43c5535b9',
|
||||
'com.android.support:support-v4:ed4cda7c752f51d33f9bbdfff3422b425b323d356cd1bdc9786aa413c912e594',
|
||||
'com.android.support:support-vector-drawable:2697503d3e8e709023ae176ba5db7f98ca0aa0b4e6290aedcb3c371904806bf7',
|
||||
'com.android.support:animated-vector-drawable:6d05cb63d1f68900220f85c56dfe1066a9bb19cb0ec1247cc68fc2ba32f6b4a7',
|
||||
@ -222,8 +227,8 @@ android {
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
@ -257,6 +262,7 @@ android {
|
||||
'proguard-retrofit.pro',
|
||||
'proguard-webrtc.pro',
|
||||
'proguard-klinker.pro',
|
||||
'proguard-retrolambda.pro',
|
||||
'proguard.cfg'
|
||||
testProguardFiles 'proguard-automation.pro',
|
||||
'proguard.cfg'
|
||||
|
2
proguard-retrolambda.pro
Normal file
2
proguard-retrolambda.pro
Normal file
@ -0,0 +1,2 @@
|
||||
-dontwarn java.lang.invoke.*
|
||||
-dontwarn **$$Lambda$*
|
@ -10,6 +10,7 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
@ -92,7 +93,7 @@ public class DatabaseMigrationActivity extends PassphraseRequiredActionBarActivi
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(DatabaseMigrationActivity.this, ApplicationMigrationService.class);
|
||||
intent.setAction(ApplicationMigrationService.MIGRATE_DATABASE);
|
||||
intent.putExtra("master_secret", getIntent().getParcelableExtra("master_secret"));
|
||||
intent.putExtra("master_secret", (Parcelable)getIntent().getParcelableExtra("master_secret"));
|
||||
startService(intent);
|
||||
|
||||
promptLayout.setVisibility(View.GONE);
|
||||
|
@ -10,18 +10,22 @@ import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class RecipientPreferenceDatabase extends Database {
|
||||
|
||||
private static final String TAG = RecipientPreferenceDatabase.class.getSimpleName();
|
||||
private static final String RECIPIENT_PREFERENCES_URI = "content://textsecure/recipients/";
|
||||
|
||||
private static final String TABLE_NAME = "recipient_preferences";
|
||||
static final String TABLE_NAME = "recipient_preferences";
|
||||
private static final String ID = "_id";
|
||||
private static final String ADDRESS = "recipient_ids";
|
||||
private static final String BLOCK = "block";
|
||||
@ -33,6 +37,14 @@ public class RecipientPreferenceDatabase extends Database {
|
||||
private static final String DEFAULT_SUBSCRIPTION_ID = "default_subscription_id";
|
||||
private static final String EXPIRE_MESSAGES = "expire_messages";
|
||||
|
||||
private static final String[] RECIPIENT_PROJECTION = new String[] {
|
||||
BLOCK, NOTIFICATION, VIBRATE, MUTE_UNTIL, COLOR, SEEN_INVITE_REMINDER, DEFAULT_SUBSCRIPTION_ID, EXPIRE_MESSAGES
|
||||
};
|
||||
|
||||
static final List<String> TYPED_RECIPIENT_PROJECTION = Stream.of(RECIPIENT_PROJECTION)
|
||||
.map(columnName -> TABLE_NAME + "." + columnName)
|
||||
.toList();
|
||||
|
||||
public enum VibrateState {
|
||||
DEFAULT(0), ENABLED(1), DISABLED(2);
|
||||
|
||||
@ -91,6 +103,16 @@ 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 Optional.absent();
|
||||
} finally {
|
||||
if (cursor != null) cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
@ -110,18 +132,10 @@ public class RecipientPreferenceDatabase extends Database {
|
||||
color = null;
|
||||
}
|
||||
|
||||
Log.w(TAG, "Muted until: " + muteUntil);
|
||||
|
||||
return Optional.of(new RecipientsPreferences(blocked, muteUntil,
|
||||
return new RecipientsPreferences(blocked, muteUntil,
|
||||
VibrateState.fromId(vibrateState),
|
||||
notificationUri, color, seenInviteReminder,
|
||||
defaultSubscriptionId, expireMessages));
|
||||
}
|
||||
|
||||
return Optional.absent();
|
||||
} finally {
|
||||
if (cursor != null) cursor.close();
|
||||
}
|
||||
defaultSubscriptionId, expireMessages);
|
||||
}
|
||||
|
||||
public void setColor(Recipient recipient, MaterialColor color) {
|
||||
|
@ -27,9 +27,12 @@ import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
|
||||
import org.thoughtcrime.securesms.database.model.DisplayRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
@ -83,6 +86,19 @@ public class ThreadDatabase extends Database {
|
||||
"CREATE INDEX IF NOT EXISTS archived_count_index ON " + TABLE_NAME + " (" + ARCHIVED + ", " + MESSAGE_COUNT + ");",
|
||||
};
|
||||
|
||||
private static final String[] THREAD_PROJECTION = {
|
||||
ID, DATE, MESSAGE_COUNT, ADDRESS, SNIPPET, SNIPPET_CHARSET, READ, TYPE, ERROR, SNIPPET_TYPE,
|
||||
SNIPPET_URI, ARCHIVED, STATUS, RECEIPT_COUNT, EXPIRES_IN, LAST_SEEN
|
||||
};
|
||||
|
||||
private static final List<String> TYPED_THREAD_PROJECTION = Stream.of(THREAD_PROJECTION)
|
||||
.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();
|
||||
|
||||
public ThreadDatabase(Context context, SQLiteOpenHelper databaseHelper) {
|
||||
super(context, databaseHelper);
|
||||
}
|
||||
@ -316,17 +332,22 @@ public class ThreadDatabase extends Database {
|
||||
}
|
||||
|
||||
public Cursor getConversationList() {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
Cursor cursor = db.query(TABLE_NAME, null, ARCHIVED + " = ? AND " + MESSAGE_COUNT + " != 0", new String[] {"0"}, null, null, DATE + " DESC");
|
||||
|
||||
setNotifyConverationListListeners(cursor);
|
||||
|
||||
return cursor;
|
||||
return getConversationList("0");
|
||||
}
|
||||
|
||||
public Cursor getArchivedConversationList() {
|
||||
return getConversationList("1");
|
||||
}
|
||||
|
||||
private Cursor getConversationList(String archived) {
|
||||
String projection = Util.join(COMBINED_THREAD_RECIPIENT_PROJECTION, ",");
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
Cursor cursor = db.query(TABLE_NAME, null, ARCHIVED + " = ? AND " + MESSAGE_COUNT + " != 0", new String[] {"1"}, null, null, DATE + " DESC");
|
||||
Cursor cursor = db.rawQuery("SELECT " + projection + " FROM " + TABLE_NAME +
|
||||
" LEFT OUTER JOIN " + RecipientPreferenceDatabase.TABLE_NAME +
|
||||
" ON " + TABLE_NAME + "." + ADDRESS + " = " + RecipientPreferenceDatabase.TABLE_NAME + "." + ADDRESS +
|
||||
" WHERE " + ARCHIVED + " = ? AND " + MESSAGE_COUNT + " != 0" +
|
||||
" ORDER BY " + TABLE_NAME + "." + DATE + " DESC",
|
||||
new String[] {archived});
|
||||
|
||||
setNotifyConverationListListeners(cursor);
|
||||
|
||||
@ -335,7 +356,13 @@ public class ThreadDatabase extends Database {
|
||||
|
||||
public Cursor getDirectShareList() {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
return db.query(TABLE_NAME, null, null, null, null, null, DATE + " DESC");
|
||||
String projection = Util.join(COMBINED_THREAD_RECIPIENT_PROJECTION, ",");
|
||||
|
||||
return db.rawQuery("SELECT " + projection + " FROM " + TABLE_NAME +
|
||||
" LEFT OUTER JOIN " + RecipientPreferenceDatabase.TABLE_NAME +
|
||||
" ON " + TABLE_NAME + "." + ADDRESS + " = " + RecipientPreferenceDatabase.TABLE_NAME + "." + ADDRESS +
|
||||
" ORDER BY " + TABLE_NAME + "." + DATE + " DESC",
|
||||
null);
|
||||
}
|
||||
|
||||
public int getArchivedConversationListCount() {
|
||||
@ -576,7 +603,8 @@ 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)));
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, address, true);
|
||||
RecipientsPreferences preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientPreferences(cursor);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, address, preferences, true);
|
||||
|
||||
DisplayRecord.Body body = getPlaintextBody(cursor);
|
||||
long date = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.DATE));
|
||||
|
@ -21,6 +21,9 @@ import android.content.Intent;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
public class RecipientFactory {
|
||||
|
||||
@ -30,7 +33,12 @@ public class RecipientFactory {
|
||||
|
||||
public static @NonNull Recipient getRecipientFor(@NonNull Context context, @NonNull Address address, boolean asynchronous) {
|
||||
if (address == null) throw new AssertionError(address);
|
||||
return provider.getRecipient(context, address, asynchronous);
|
||||
return provider.getRecipient(context, address, Optional.absent(), asynchronous);
|
||||
}
|
||||
|
||||
public static @NonNull Recipient getRecipientFor(@NonNull Context context, @NonNull Address address, @NonNull RecipientsPreferences preferences, boolean asynchronous) {
|
||||
if (address == null) throw new AssertionError(address);
|
||||
return provider.getRecipient(context, address, Optional.of(preferences), asynchronous);
|
||||
}
|
||||
|
||||
public static void clearCache(Context context) {
|
||||
|
@ -68,16 +68,16 @@ class RecipientProvider {
|
||||
null, null));
|
||||
}};
|
||||
|
||||
@NonNull Recipient getRecipient(Context context, Address address, boolean asynchronous) {
|
||||
@NonNull Recipient getRecipient(Context context, Address address, Optional<RecipientsPreferences> preferences, boolean asynchronous) {
|
||||
Recipient cachedRecipient = recipientCache.get(address);
|
||||
if (cachedRecipient != null && !cachedRecipient.isStale() && (asynchronous || !cachedRecipient.isResolving())) {
|
||||
return cachedRecipient;
|
||||
}
|
||||
|
||||
if (asynchronous) {
|
||||
cachedRecipient = new Recipient(address, cachedRecipient, getRecipientDetailsAsync(context, address));
|
||||
cachedRecipient = new Recipient(address, cachedRecipient, getRecipientDetailsAsync(context, address, preferences));
|
||||
} else {
|
||||
cachedRecipient = new Recipient(address, getRecipientDetailsSync(context, address, false));
|
||||
cachedRecipient = new Recipient(address, getRecipientDetailsSync(context, address, preferences, false));
|
||||
}
|
||||
|
||||
recipientCache.set(address, cachedRecipient);
|
||||
@ -88,12 +88,12 @@ class RecipientProvider {
|
||||
recipientCache.reset();
|
||||
}
|
||||
|
||||
private @NonNull ListenableFutureTask<RecipientDetails> getRecipientDetailsAsync(final Context context, final @NonNull Address address)
|
||||
private @NonNull ListenableFutureTask<RecipientDetails> getRecipientDetailsAsync(final Context context, final @NonNull Address address, final @NonNull Optional<RecipientsPreferences> preferences)
|
||||
{
|
||||
Callable<RecipientDetails> task = new Callable<RecipientDetails>() {
|
||||
@Override
|
||||
public RecipientDetails call() throws Exception {
|
||||
return getRecipientDetailsSync(context, address, true);
|
||||
return getRecipientDetailsSync(context, address, preferences, true);
|
||||
}
|
||||
};
|
||||
|
||||
@ -102,13 +102,15 @@ class RecipientProvider {
|
||||
return future;
|
||||
}
|
||||
|
||||
private @NonNull RecipientDetails getRecipientDetailsSync(Context context, @NonNull Address address, boolean nestedAsynchronous) {
|
||||
private @NonNull RecipientDetails getRecipientDetailsSync(Context context, @NonNull Address address, Optional<RecipientsPreferences> preferences, boolean nestedAsynchronous) {
|
||||
if (address.isGroup()) return getGroupRecipientDetails(context, address, nestedAsynchronous);
|
||||
else return getIndividualRecipientDetails(context, address);
|
||||
else return getIndividualRecipientDetails(context, address, preferences);
|
||||
}
|
||||
|
||||
private @NonNull RecipientDetails getIndividualRecipientDetails(Context context, @NonNull Address address) {
|
||||
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(address);
|
||||
private @NonNull RecipientDetails getIndividualRecipientDetails(Context context, @NonNull Address address, Optional<RecipientsPreferences> preferences) {
|
||||
if (!preferences.isPresent()) {
|
||||
preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(address);
|
||||
}
|
||||
|
||||
if (address.isPhone() && !TextUtils.isEmpty(address.toPhoneString())) {
|
||||
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(address.toPhoneString()));
|
||||
@ -149,7 +151,7 @@ class RecipientProvider {
|
||||
List<Recipient> members = new LinkedList<>();
|
||||
|
||||
for (Address memberAddress : memberAddresses) {
|
||||
members.add(getRecipient(context, memberAddress, asynchronous));
|
||||
members.add(getRecipient(context, memberAddress, Optional.absent(), asynchronous));
|
||||
}
|
||||
|
||||
if (!groupId.isMmsGroup() && title == null) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user