diff --git a/res/layout/contact_selection_list_item.xml b/res/layout/contact_selection_list_item.xml
index bbab6b99ce..2169819ed0 100644
--- a/res/layout/contact_selection_list_item.xml
+++ b/res/layout/contact_selection_list_item.xml
@@ -29,7 +29,7 @@
android:layout_marginEnd="16dp"
android:orientation="vertical">
-
+ tools:text="Ottttooooooooo Ocataaaaaaaavius" />
> SEARCH_CURSOR_MAPPERS = new ArrayList>() {{
+ add(new Pair<>(ID_COLUMN, cursor -> cursor.getLong(cursor.getColumnIndexOrThrow(RecipientDatabase.ID))));
+
+ add(new Pair<>(NAME_COLUMN, cursor -> {
+ String system = cursor.getString(cursor.getColumnIndexOrThrow(RecipientDatabase.SYSTEM_DISPLAY_NAME));
+ String profile = cursor.getString(cursor.getColumnIndexOrThrow(RecipientDatabase.SIGNAL_PROFILE_NAME));
+
+ return !TextUtils.isEmpty(system) ? system : profile;
+ }));
+
+ add(new Pair<>(NUMBER_COLUMN, cursor -> {
+ String phone = cursor.getString(cursor.getColumnIndexOrThrow(RecipientDatabase.PHONE));
+ String email = cursor.getString(cursor.getColumnIndexOrThrow(RecipientDatabase.EMAIL));
+
+ return !TextUtils.isEmpty(phone) ? phone : email;
+ }));
+
+ add(new Pair<>(NUMBER_TYPE_COLUMN, cursor -> cursor.getInt(cursor.getColumnIndexOrThrow(RecipientDatabase.SYSTEM_PHONE_TYPE))));
+
+ add(new Pair<>(LABEL_COLUMN, cursor -> cursor.getString(cursor.getColumnIndexOrThrow(RecipientDatabase.SYSTEM_PHONE_LABEL))));
+
+ add(new Pair<>(CONTACT_TYPE_COLUMN, cursor -> {
+ int registered = cursor.getInt(cursor.getColumnIndexOrThrow(RecipientDatabase.REGISTERED));
+ return registered == RecipientDatabase.RegisteredState.REGISTERED.getId() ? PUSH_TYPE : NORMAL_TYPE;
+ }));
+ }};
+
+ public ContactRepository(@NonNull Context context) {
+ this.recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
+ this.noteToSelfTitle = context.getString(R.string.note_to_self);
+ }
+
+ @WorkerThread
+ public Cursor querySignalContacts(@NonNull String query) {
+ Cursor cursor = TextUtils.isEmpty(query) ? recipientDatabase.getSignalContacts()
+ : recipientDatabase.querySignalContacts(query);
+
+
+ if (noteToSelfTitle.toLowerCase().contains(query.toLowerCase())) {
+ Recipient self = Recipient.self();
+ boolean nameMatch = self.getDisplayName().toLowerCase().contains(query.toLowerCase());
+ boolean numberMatch = self.requireAddress().serialize() != null && self.requireAddress().serialize().contains(query);
+ boolean shouldAdd = !nameMatch && !numberMatch;
+
+ if (shouldAdd) {
+ MatrixCursor selfCursor = new MatrixCursor(RecipientDatabase.SEARCH_PROJECTION);
+ selfCursor.addRow(new Object[]{ self.getId().serialize(), noteToSelfTitle, null, self.requireAddress().serialize(), null, null, -1, RecipientDatabase.RegisteredState.REGISTERED.getId(), noteToSelfTitle });
+
+ cursor = cursor == null ? selfCursor : new MergeCursor(new Cursor[]{ cursor, selfCursor });
+ }
+ }
+
+ return new SearchCursorWrapper(cursor, SEARCH_CURSOR_MAPPERS);
+ }
+
+ @WorkerThread
+ public Cursor queryNonSignalContacts(@NonNull String query) {
+ Cursor cursor = TextUtils.isEmpty(query) ? recipientDatabase.getNonSignalContacts()
+ : recipientDatabase.queryNonSignalContacts(query);
+ return new SearchCursorWrapper(cursor, SEARCH_CURSOR_MAPPERS);
+ }
+
+
+ /**
+ * This lets us mock the legacy cursor interface while using the new cursor, even though the data
+ * doesn't quite match up exactly.
+ */
+ private static class SearchCursorWrapper extends CursorWrapper {
+
+ private final Cursor wrapped;
+ private final String[] columnNames;
+ private final List> mappers;
+ private final Map positions;
+
+ SearchCursorWrapper(Cursor cursor, @NonNull List> mappers) {
+ super(cursor);
+
+ this.wrapped = cursor;
+ this.mappers = mappers;
+ this.positions = new HashMap<>();
+ this.columnNames = new String[mappers.size()];
+
+ for (int i = 0; i < mappers.size(); i++) {
+ Pair pair = mappers.get(i);
+
+ positions.put(pair.first(), i);
+ columnNames[i] = pair.first();
+ }
+ }
+
+ @Override
+ public int getColumnCount() {
+ return mappers.size();
+ }
+
+ @Override
+ public String[] getColumnNames() {
+ return columnNames;
+ }
+
+ @Override
+ public int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException {
+ Integer index = positions.get(columnName);
+
+ if (index != null) {
+ return index;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public String getString(int columnIndex) {
+ return String.valueOf(mappers.get(columnIndex).second().get(wrapped));
+ }
+
+ @Override
+ public int getInt(int columnIndex) {
+ return (int) mappers.get(columnIndex).second().get(wrapped);
+ }
+
+ @Override
+ public long getLong(int columnIndex) {
+ return (long) mappers.get(columnIndex).second().get(wrapped);
+ }
+ }
+
+ private interface ValueMapper {
+ T get(@NonNull Cursor cursor);
+ }
+}
diff --git a/src/org/thoughtcrime/securesms/contacts/ContactSelectionListAdapter.java b/src/org/thoughtcrime/securesms/contacts/ContactSelectionListAdapter.java
index 49751a3c54..23f338a423 100644
--- a/src/org/thoughtcrime/securesms/contacts/ContactSelectionListAdapter.java
+++ b/src/org/thoughtcrime/securesms/contacts/ContactSelectionListAdapter.java
@@ -39,6 +39,7 @@ import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter.ViewHolde
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.GlideRequests;
+import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration.StickyHeaderAdapter;
import org.thoughtcrime.securesms.util.Util;
@@ -77,7 +78,7 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter getContactsCursors() {
- ContactsDatabase contactsDatabase = DatabaseFactory.getContactsDatabase(getContext());
- List cursorList = new ArrayList<>(2);
+ List cursorList = new ArrayList<>(2);
if (!Permissions.hasAny(getContext(), Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS)) {
return cursorList;
}
if (pushEnabled(mode)) {
- cursorList.add(contactsDatabase.queryTextSecureContacts(filter));
+ cursorList.add(contactRepository.querySignalContacts(filter));
}
if (pushEnabled(mode) && smsEnabled(mode)) {
- cursorList.add(contactsDatabase.querySystemContacts(filter));
+ cursorList.add(contactRepository.queryNonSignalContacts(filter));
} else if (smsEnabled(mode)) {
- cursorList.add(filterNonPushContacts(contactsDatabase.querySystemContacts(filter)));
+ cursorList.add(filterNonPushContacts(contactRepository.queryNonSignalContacts(filter)));
}
return cursorList;
}
@@ -203,11 +211,12 @@ public class ContactsCursorLoader extends CursorLoader {
try (GroupDatabase.Reader reader = DatabaseFactory.getGroupDatabase(getContext()).getGroupsFilteredByTitle(filter)) {
GroupDatabase.GroupRecord groupRecord;
while ((groupRecord = reader.getNext()) != null) {
- groupContacts.addRow(new Object[] { groupRecord.getTitle(),
+ groupContacts.addRow(new Object[] { groupRecord.getRecipientId().serialize(),
+ groupRecord.getTitle(),
groupRecord.getEncodedId(),
ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM,
"",
- ContactsDatabase.NORMAL_TYPE });
+ ContactRepository.NORMAL_TYPE });
}
}
return groupContacts;
@@ -215,11 +224,12 @@ public class ContactsCursorLoader extends CursorLoader {
private Cursor getNewNumberCursor() {
MatrixCursor newNumberCursor = new MatrixCursor(CONTACT_PROJECTION, 1);
- newNumberCursor.addRow(new Object[] { getContext().getString(R.string.contact_selection_list__unknown_contact),
+ newNumberCursor.addRow(new Object[] { null,
+ getContext().getString(R.string.contact_selection_list__unknown_contact),
filter,
ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM,
"\u21e2",
- ContactsDatabase.NEW_TYPE });
+ ContactRepository.NEW_TYPE });
return newNumberCursor;
}
@@ -228,15 +238,16 @@ public class ContactsCursorLoader extends CursorLoader {
final long startMillis = System.currentTimeMillis();
final MatrixCursor matrix = new MatrixCursor(CONTACT_PROJECTION);
while (cursor.moveToNext()) {
- final String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_COLUMN));
- final Recipient recipient = Recipient.external(getContext(), number);
+ final RecipientId id = RecipientId.from(cursor.getLong(cursor.getColumnIndexOrThrow(ContactRepository.ID_COLUMN)));
+ final Recipient recipient = Recipient.resolved(id);
if (recipient.resolve().getRegistered() != RecipientDatabase.RegisteredState.REGISTERED) {
- matrix.addRow(new Object[]{cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NAME_COLUMN)),
- number,
- cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_TYPE_COLUMN)),
- cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.LABEL_COLUMN)),
- ContactsDatabase.NORMAL_TYPE});
+ matrix.addRow(new Object[]{cursor.getLong(cursor.getColumnIndexOrThrow(ContactRepository.ID_COLUMN)),
+ cursor.getString(cursor.getColumnIndexOrThrow(ContactRepository.NAME_COLUMN)),
+ cursor.getString(cursor.getColumnIndexOrThrow(ContactRepository.NUMBER_COLUMN)),
+ cursor.getString(cursor.getColumnIndexOrThrow(ContactRepository.NUMBER_TYPE_COLUMN)),
+ cursor.getString(cursor.getColumnIndexOrThrow(ContactRepository.LABEL_COLUMN)),
+ ContactRepository.NORMAL_TYPE});
}
}
Log.i(TAG, "filterNonPushContacts() -> " + (System.currentTimeMillis() - startMillis) + "ms");
diff --git a/src/org/thoughtcrime/securesms/contacts/ContactsDatabase.java b/src/org/thoughtcrime/securesms/contacts/ContactsDatabase.java
index 3a5f1d4a1e..26d1482a3f 100644
--- a/src/org/thoughtcrime/securesms/contacts/ContactsDatabase.java
+++ b/src/org/thoughtcrime/securesms/contacts/ContactsDatabase.java
@@ -17,31 +17,23 @@
package org.thoughtcrime.securesms.contacts;
import android.accounts.Account;
-import android.annotation.SuppressLint;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
-import android.database.CursorWrapper;
-import android.database.MatrixCursor;
-import android.database.MergeCursor;
import android.net.Uri;
-import android.os.Build;
import android.os.RemoteException;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.ContactsContract.RawContacts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import android.text.TextUtils;
-import android.util.Pair;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
@@ -64,18 +56,6 @@ public class ContactsDatabase {
private static final String CALL_MIMETYPE = "vnd.android.cursor.item/vnd.org.thoughtcrime.securesms.call";
private static final String SYNC = "__TS";
- static final String NAME_COLUMN = "name";
- static final String NUMBER_COLUMN = "number";
- static final String NUMBER_TYPE_COLUMN = "number_type";
- static final String LABEL_COLUMN = "label";
- static final String CONTACT_TYPE_COLUMN = "contact_type";
-
- static final int NORMAL_TYPE = 0;
- static final int PUSH_TYPE = 1;
- static final int NEW_TYPE = 2;
- static final int RECENT_TYPE = 3;
- static final int DIVIDER_TYPE = 4;
-
private final Context context;
public ContactsDatabase(Context context) {
@@ -151,109 +131,6 @@ public class ContactsDatabase {
}
}
- @SuppressLint("Recycle")
- public @NonNull Cursor querySystemContacts(@Nullable String filter) {
- Uri uri;
-
- if (!TextUtils.isEmpty(filter)) {
- uri = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, Uri.encode(filter));
- } else {
- uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
- }
-
- if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- uri = uri.buildUpon().appendQueryParameter(ContactsContract.REMOVE_DUPLICATE_ENTRIES, "true").build();
- }
-
- String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
- ContactsContract.CommonDataKinds.Phone.NUMBER,
- ContactsContract.CommonDataKinds.Phone.TYPE,
- ContactsContract.CommonDataKinds.Phone.LABEL};
-
- String sort = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
-
- Map projectionMap = new HashMap() {{
- put(NAME_COLUMN, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
- put(NUMBER_COLUMN, ContactsContract.CommonDataKinds.Phone.NUMBER);
- put(NUMBER_TYPE_COLUMN, ContactsContract.CommonDataKinds.Phone.TYPE);
- put(LABEL_COLUMN, ContactsContract.CommonDataKinds.Phone.LABEL);
- }};
-
- String formattedNumber = "REPLACE(REPLACE(REPLACE(REPLACE(data1,' ',''),'-',''),'(',''),')','')";
- String excludeSelection = "(" + formattedNumber +" NOT IN " +
- "(SELECT data1 FROM view_data WHERE "+formattedNumber+" = data1) " +
- "OR "+formattedNumber+" = data1)" +
- "AND " + formattedNumber + "NOT IN (SELECT "+formattedNumber+" FROM view_data where mimetype = '"+CONTACT_MIMETYPE+"')" ;
-
- String fallbackSelection = ContactsContract.Data.SYNC2 + " IS NULL OR " + ContactsContract.Data.SYNC2 + " != '" + SYNC + "'";
-
- Cursor cursor;
-
- try {
- cursor = context.getContentResolver().query(uri, projection, excludeSelection, null, sort);
- } catch (Exception e) {
- Log.w(TAG, e);
- cursor = context.getContentResolver().query(uri, projection, fallbackSelection, null, sort);
- }
-
- return new ProjectionMappingCursor(cursor, projectionMap, new Pair<>(CONTACT_TYPE_COLUMN, NORMAL_TYPE));
- }
-
- @SuppressLint("Recycle")
- public @NonNull Cursor queryTextSecureContacts(String filter) {
- String[] projection = new String[] {ContactsContract.Contacts.DISPLAY_NAME,
- ContactsContract.Data.DATA1};
-
- String sort = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
-
- Map projectionMap = new HashMap(){{
- put(NAME_COLUMN, ContactsContract.Contacts.DISPLAY_NAME);
- put(NUMBER_COLUMN, ContactsContract.Data.DATA1);
- }};
-
- Cursor cursor;
-
- if (TextUtils.isEmpty(filter)) {
- cursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
- projection,
- ContactsContract.Data.MIMETYPE + " = ?",
- new String[] {CONTACT_MIMETYPE},
- sort);
- } else {
- cursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
- projection,
- ContactsContract.Data.MIMETYPE + " = ? AND (" + ContactsContract.Contacts.DISPLAY_NAME + " LIKE ? OR " + ContactsContract.Data.DATA1 + " LIKE ?)",
- new String[] {CONTACT_MIMETYPE,
- "%" + filter + "%", "%" + filter + "%"},
- sort);
-
- if (context.getString(R.string.note_to_self).toLowerCase().contains(filter.toLowerCase())) {
- Optional self = getSystemContactInfo(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
- boolean shouldAdd = true;
-
- if (self.isPresent()) {
- boolean nameMatch = self.get().name != null && self.get().name.toLowerCase().contains(filter.toLowerCase());
- boolean numberMatch = self.get().number != null && self.get().number.contains(filter);
-
- shouldAdd = !nameMatch && !numberMatch;
- }
-
- if (shouldAdd) {
- MatrixCursor selfCursor = new MatrixCursor(projection);
- selfCursor.addRow(new Object[]{ context.getString(R.string.note_to_self), TextSecurePreferences.getLocalNumber(context)});
-
- cursor = cursor == null ? selfCursor : new MergeCursor(new Cursor[]{ cursor, selfCursor });
- }
- }
- }
-
- return new ProjectionMappingCursor(cursor, projectionMap,
- new Pair<>(LABEL_COLUMN, "TextSecure"),
- new Pair<>(NUMBER_TYPE_COLUMN, 0),
- new Pair<>(CONTACT_TYPE_COLUMN, PUSH_TYPE));
-
- }
-
public @Nullable Cursor getNameDetails(long contactId) {
String[] projection = new String[] { ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
@@ -573,105 +450,6 @@ public class ContactsDatabase {
}
}
- private static class ProjectionMappingCursor extends CursorWrapper {
-
- private final Map projectionMap;
- private final Pair[] extras;
-
- @SafeVarargs
- ProjectionMappingCursor(Cursor cursor,
- Map projectionMap,
- Pair... extras)
- {
- super(cursor);
- this.projectionMap = projectionMap;
- this.extras = extras;
- }
-
- @Override
- public int getColumnCount() {
- return super.getColumnCount() + extras.length;
- }
-
- @Override
- public int getColumnIndex(String columnName) {
- for (int i=0;i= baseColumnCount) {
- int offset = columnIndex - baseColumnCount;
- return extras[offset].first;
- }
-
- return getReverseProjection(super.getColumnName(columnIndex));
- }
-
- @Override
- public String[] getColumnNames() {
- String[] names = super.getColumnNames();
- String[] allNames = new String[names.length + extras.length];
-
- for (int i=0;i= super.getColumnCount()) {
- int offset = columnIndex - super.getColumnCount();
- return (Integer)extras[offset].second;
- }
-
- return super.getInt(columnIndex);
- }
-
- @Override
- public String getString(int columnIndex) {
- if (columnIndex >= super.getColumnCount()) {
- int offset = columnIndex - super.getColumnCount();
- return (String)extras[offset].second;
- }
-
- return super.getString(columnIndex);
- }
-
-
- private @Nullable String getReverseProjection(String columnName) {
- for (Map.Entry entry : projectionMap.entrySet()) {
- if (entry.getValue().equals(columnName)) {
- return entry.getKey();
- }
- }
-
- return null;
- }
- }
-
private static class SystemContactInfo {
private final String name;
private final String number;
diff --git a/src/org/thoughtcrime/securesms/contactshare/ContactShareEditActivity.java b/src/org/thoughtcrime/securesms/contactshare/ContactShareEditActivity.java
index 785aecff88..394074627c 100644
--- a/src/org/thoughtcrime/securesms/contactshare/ContactShareEditActivity.java
+++ b/src/org/thoughtcrime/securesms/contactshare/ContactShareEditActivity.java
@@ -75,7 +75,7 @@ public class ContactShareEditActivity extends PassphraseRequiredActionBarActivit
ContactShareEditAdapter contactAdapter = new ContactShareEditAdapter(GlideApp.with(this), dynamicLanguage.getCurrentLocale(), this);
contactList.setAdapter(contactAdapter);
- ContactRepository contactRepository = new ContactRepository(this,
+ SharedContactRepository contactRepository = new SharedContactRepository(this,
AsyncTask.THREAD_POOL_EXECUTOR,
DatabaseFactory.getContactsDatabase(this));
diff --git a/src/org/thoughtcrime/securesms/contactshare/ContactShareEditViewModel.java b/src/org/thoughtcrime/securesms/contactshare/ContactShareEditViewModel.java
index 860729cd45..d5e342177d 100644
--- a/src/org/thoughtcrime/securesms/contactshare/ContactShareEditViewModel.java
+++ b/src/org/thoughtcrime/securesms/contactshare/ContactShareEditViewModel.java
@@ -19,10 +19,10 @@ class ContactShareEditViewModel extends ViewModel {
private final MutableLiveData> contacts;
private final SingleLiveEvent events;
- private final ContactRepository repo;
+ private final SharedContactRepository repo;
ContactShareEditViewModel(@NonNull List contactUris,
- @NonNull ContactRepository contactRepository)
+ @NonNull SharedContactRepository contactRepository)
{
contacts = new MutableLiveData<>();
events = new SingleLiveEvent<>();
@@ -98,9 +98,9 @@ class ContactShareEditViewModel extends ViewModel {
static class Factory extends ViewModelProvider.NewInstanceFactory {
private final List contactUris;
- private final ContactRepository contactRepository;
+ private final SharedContactRepository contactRepository;
- Factory(@NonNull List contactUris, @NonNull ContactRepository contactRepository) {
+ Factory(@NonNull List contactUris, @NonNull SharedContactRepository contactRepository) {
this.contactUris = contactUris;
this.contactRepository = contactRepository;
}
diff --git a/src/org/thoughtcrime/securesms/contactshare/ContactRepository.java b/src/org/thoughtcrime/securesms/contactshare/SharedContactRepository.java
similarity index 97%
rename from src/org/thoughtcrime/securesms/contactshare/ContactRepository.java
rename to src/org/thoughtcrime/securesms/contactshare/SharedContactRepository.java
index 4d49b32826..4289fa5a27 100644
--- a/src/org/thoughtcrime/securesms/contactshare/ContactRepository.java
+++ b/src/org/thoughtcrime/securesms/contactshare/SharedContactRepository.java
@@ -15,7 +15,6 @@ import org.thoughtcrime.securesms.contactshare.Contact.Email;
import org.thoughtcrime.securesms.contactshare.Contact.Name;
import org.thoughtcrime.securesms.contactshare.Contact.Phone;
import org.thoughtcrime.securesms.contactshare.Contact.PostalAddress;
-import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
@@ -36,17 +35,17 @@ import ezvcard.VCard;
import static org.thoughtcrime.securesms.contactshare.Contact.*;
-public class ContactRepository {
+public class SharedContactRepository {
- private static final String TAG = ContactRepository.class.getSimpleName();
+ private static final String TAG = SharedContactRepository.class.getSimpleName();
private final Context context;
private final Executor executor;
private final ContactsDatabase contactsDatabase;
- ContactRepository(@NonNull Context context,
- @NonNull Executor executor,
- @NonNull ContactsDatabase contactsDatabase)
+ SharedContactRepository(@NonNull Context context,
+ @NonNull Executor executor,
+ @NonNull ContactsDatabase contactsDatabase)
{
this.context = context.getApplicationContext();
this.executor = executor;
diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationSearchViewModel.java b/src/org/thoughtcrime/securesms/conversation/ConversationSearchViewModel.java
index d83055071f..76bb06b28f 100644
--- a/src/org/thoughtcrime/securesms/conversation/ConversationSearchViewModel.java
+++ b/src/org/thoughtcrime/securesms/conversation/ConversationSearchViewModel.java
@@ -7,6 +7,7 @@ import android.content.Context;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.contacts.ContactAccessor;
+import org.thoughtcrime.securesms.contacts.ContactRepository;
import org.thoughtcrime.securesms.database.CursorList;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.search.SearchRepository;
@@ -37,8 +38,8 @@ public class ConversationSearchViewModel extends AndroidViewModel {
debouncer = new Debouncer(500);
searchRepository = new SearchRepository(context,
DatabaseFactory.getSearchDatabase(context),
- DatabaseFactory.getContactsDatabase(context),
DatabaseFactory.getThreadDatabase(context),
+ new ContactRepository(application),
ContactAccessor.getInstance(),
SignalExecutors.SERIAL);
}
diff --git a/src/org/thoughtcrime/securesms/database/RecipientDatabase.java b/src/org/thoughtcrime/securesms/database/RecipientDatabase.java
index 574115e53d..fee1370c65 100644
--- a/src/org/thoughtcrime/securesms/database/RecipientDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/RecipientDatabase.java
@@ -4,6 +4,8 @@ import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
+import android.text.TextUtils;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -36,8 +38,8 @@ public class RecipientDatabase extends Database {
static final String TABLE_NAME = "recipient";
public static final String ID = "_id";
private static final String UUID = "uuid";
- static final String PHONE = "phone";
- static final String EMAIL = "email";
+ public static final String PHONE = "phone";
+ public static final String EMAIL = "email";
static final String GROUP_ID = "group_id";
private static final String BLOCKED = "blocked";
private static final String MESSAGE_RINGTONE = "message_ringtone";
@@ -50,22 +52,25 @@ public class RecipientDatabase extends Database {
private static final String SEEN_INVITE_REMINDER = "seen_invite_reminder";
private static final String DEFAULT_SUBSCRIPTION_ID = "default_subscription_id";
private static final String MESSAGE_EXPIRATION_TIME = "message_expiration_time";
- static final String REGISTERED = "registered";
- private static final String SYSTEM_DISPLAY_NAME = "system_display_name";
+ public static final String REGISTERED = "registered";
+ public static final String SYSTEM_DISPLAY_NAME = "system_display_name";
private static final String SYSTEM_PHOTO_URI = "system_photo_uri";
- private static final String SYSTEM_PHONE_LABEL = "system_phone_label";
+ public static final String SYSTEM_PHONE_TYPE = "system_phone_type";
+ public static final String SYSTEM_PHONE_LABEL = "system_phone_label";
private static final String SYSTEM_CONTACT_URI = "system_contact_uri";
private static final String PROFILE_KEY = "profile_key";
- private static final String SIGNAL_PROFILE_NAME = "signal_profile_name";
+ public static final String SIGNAL_PROFILE_NAME = "signal_profile_name";
private static final String SIGNAL_PROFILE_AVATAR = "signal_profile_avatar";
private static final String PROFILE_SHARING = "profile_sharing";
private static final String UNIDENTIFIED_ACCESS_MODE = "unidentified_access_mode";
private static final String FORCE_SMS_SELECTION = "force_sms_selection";
+ private static final String SORT_NAME = "sort_name";
+
private static final String[] RECIPIENT_PROJECTION = new String[] {
UUID, PHONE, EMAIL, GROUP_ID,
BLOCKED, MESSAGE_RINGTONE, CALL_RINGTONE, MESSAGE_VIBRATE, CALL_VIBRATE, MUTE_UNTIL, COLOR, SEEN_INVITE_REMINDER, DEFAULT_SUBSCRIPTION_ID, MESSAGE_EXPIRATION_TIME, REGISTERED,
- PROFILE_KEY, SYSTEM_DISPLAY_NAME, SYSTEM_PHOTO_URI, SYSTEM_PHONE_LABEL, SYSTEM_CONTACT_URI,
+ PROFILE_KEY, SYSTEM_DISPLAY_NAME, SYSTEM_PHOTO_URI, SYSTEM_PHONE_LABEL, SYSTEM_PHONE_TYPE, SYSTEM_CONTACT_URI,
SIGNAL_PROFILE_NAME, SIGNAL_PROFILE_AVATAR, PROFILE_SHARING, NOTIFICATION_CHANNEL,
UNIDENTIFIED_ACCESS_MODE,
FORCE_SMS_SELECTION,
@@ -73,6 +78,8 @@ public class RecipientDatabase extends Database {
private static final String[] ID_PROJECTION = new String[] { ID };
+ public static final String[] SEARCH_PROJECTION = new String[] { ID, SYSTEM_DISPLAY_NAME, SIGNAL_PROFILE_NAME, PHONE, EMAIL, SYSTEM_PHONE_LABEL, SYSTEM_PHONE_TYPE, REGISTERED, "IFNULL(" + SYSTEM_DISPLAY_NAME + ", " + SIGNAL_PROFILE_NAME + ") AS " + SORT_NAME };
+
private static Address addressFromCursor(Cursor cursor) {
String phone = cursor.getString(cursor.getColumnIndexOrThrow(PHONE));
String email = cursor.getString(cursor.getColumnIndexOrThrow(EMAIL));
@@ -159,6 +166,7 @@ public class RecipientDatabase extends Database {
SYSTEM_DISPLAY_NAME + " TEXT DEFAULT NULL, " +
SYSTEM_PHOTO_URI + " TEXT DEFAULT NULL, " +
SYSTEM_PHONE_LABEL + " TEXT DEFAULT NULL, " +
+ SYSTEM_PHONE_TYPE + " INTEGER DEFAULT -1, " +
SYSTEM_CONTACT_URI + " TEXT DEFAULT NULL, " +
PROFILE_KEY + " TEXT DEFAULT NULL, " +
SIGNAL_PROFILE_NAME + " TEXT DEFAULT NULL, " +
@@ -262,8 +270,7 @@ public class RecipientDatabase extends Database {
if (cursor != null && cursor.moveToNext()) {
return getRecipientSettings(cursor);
} else {
- // TODO: Maybe not make this an error?
- throw new AssertionError("Couldn't find recipient!");
+ throw new AssertionError("Couldn't find recipient! id: " + id.serialize());
}
}
}
@@ -551,6 +558,66 @@ public class RecipientDatabase extends Database {
Stream.of(updates.entrySet()).forEach(entry -> Recipient.live(entry.getKey()).refresh());
}
}
+ public @Nullable Cursor getSignalContacts() {
+ String selection = BLOCKED + " = ? AND " +
+ REGISTERED + " = ? AND " +
+ GROUP_ID + " IS NULL AND " +
+ "(" + SYSTEM_DISPLAY_NAME + " NOT NULL OR " + PROFILE_SHARING + " = ?) AND " +
+ "(" + SYSTEM_DISPLAY_NAME + " NOT NULL OR " + SIGNAL_PROFILE_NAME + " NOT NULL)";
+ String[] args = new String[] { "0", String.valueOf(RegisteredState.REGISTERED.getId()), "1" };
+ String orderBy = SORT_NAME + ", " + SYSTEM_DISPLAY_NAME + ", " + SIGNAL_PROFILE_NAME + ", " + PHONE;
+
+ return databaseHelper.getReadableDatabase().query(TABLE_NAME, SEARCH_PROJECTION, selection, args, null, null, orderBy);
+ }
+
+ public @Nullable Cursor querySignalContacts(@NonNull String query) {
+ query = TextUtils.isEmpty(query) ? "*" : query;
+ query = "%" + query + "%";
+
+ String selection = BLOCKED + " = ? AND " +
+ REGISTERED + " = ? AND " +
+ GROUP_ID + " IS NULL AND " +
+ "(" + SYSTEM_DISPLAY_NAME + " NOT NULL OR " + PROFILE_SHARING + " = ?) AND " +
+ "(" +
+ PHONE + " LIKE ? OR " +
+ SYSTEM_DISPLAY_NAME + " LIKE ? OR " +
+ SIGNAL_PROFILE_NAME + " LIKE ?" +
+ ")";
+ String[] args = new String[] { "0", String.valueOf(RegisteredState.REGISTERED.getId()), "1", query, query, query };
+ String orderBy = SORT_NAME + ", " + SYSTEM_DISPLAY_NAME + ", " + SIGNAL_PROFILE_NAME + ", " + PHONE;
+
+ return databaseHelper.getReadableDatabase().query(TABLE_NAME, SEARCH_PROJECTION, selection, args, null, null, orderBy);
+ }
+
+ public @Nullable Cursor getNonSignalContacts() {
+ String selection = BLOCKED + " = ? AND " +
+ REGISTERED + " != ? AND " +
+ GROUP_ID + " IS NULL AND " +
+ SYSTEM_DISPLAY_NAME + " NOT NULL AND " +
+ "(" + PHONE + " NOT NULL OR " + EMAIL + " NOT NULL)";
+ String[] args = new String[] { "0", String.valueOf(RegisteredState.REGISTERED.getId()) };
+ String orderBy = SYSTEM_DISPLAY_NAME + ", " + PHONE;
+
+ return databaseHelper.getReadableDatabase().query(TABLE_NAME, SEARCH_PROJECTION, selection, args, null, null, orderBy);
+ }
+
+ public @Nullable Cursor queryNonSignalContacts(@NonNull String query) {
+ query = TextUtils.isEmpty(query) ? "*" : query;
+ query = "%" + query + "%";
+
+ String selection = BLOCKED + " = ? AND " +
+ REGISTERED + " != ? AND " +
+ GROUP_ID + " IS NULL AND " +
+ "(" + PHONE + " NOT NULL OR " + EMAIL + " NOT NULL) AND " +
+ "(" +
+ PHONE + " LIKE ? OR " +
+ SYSTEM_DISPLAY_NAME + " LIKE ?" +
+ ")";
+ String[] args = new String[] { "0", String.valueOf(RegisteredState.REGISTERED.getId()), query, query };
+ String orderBy = SYSTEM_DISPLAY_NAME + ", " + PHONE;
+
+ return databaseHelper.getReadableDatabase().query(TABLE_NAME, SEARCH_PROJECTION, selection, args, null, null, orderBy);
+ }
private void update(@NonNull RecipientId id, ContentValues contentValues) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
@@ -567,11 +634,18 @@ public class RecipientDatabase extends Database {
this.database = database;
}
- public void setSystemContactInfo(@NonNull RecipientId id, @Nullable String displayName, @Nullable String photoUri, @Nullable String systemPhoneLabel, @Nullable String systemContactUri) {
+ public void setSystemContactInfo(@NonNull RecipientId id,
+ @Nullable String displayName,
+ @Nullable String photoUri,
+ @Nullable String systemPhoneLabel,
+ int systemPhoneType,
+ @Nullable String systemContactUri)
+ {
ContentValues contentValues = new ContentValues(1);
contentValues.put(SYSTEM_DISPLAY_NAME, displayName);
contentValues.put(SYSTEM_PHOTO_URI, photoUri);
contentValues.put(SYSTEM_PHONE_LABEL, systemPhoneLabel);
+ contentValues.put(SYSTEM_PHONE_TYPE, systemPhoneType);
contentValues.put(SYSTEM_CONTACT_URI, systemContactUri);
update(id, contentValues);
diff --git a/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java
index 3eec65a5f7..6e3aafe20e 100644
--- a/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java
+++ b/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java
@@ -39,6 +39,7 @@ import org.thoughtcrime.securesms.jobs.RefreshPreKeysJob;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
+import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.DelimiterUtil;
import org.thoughtcrime.securesms.util.GroupUtil;
@@ -76,6 +77,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
private static final int REVEALABLE_MESSAGES = 22;
private static final int VIEW_ONCE_ONLY = 23;
private static final int RECIPIENT_IDS = 24;
+ private static final int RECIPIENT_SEARCH = 25;
private static final int DATABASE_VERSION = 25;
private static final String DATABASE_NAME = "signal.db";
@@ -490,6 +492,27 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
RecipientIdMigrationHelper.execute(db);
}
+ if (oldVersion < RECIPIENT_SEARCH) {
+ db.execSQL("ALTER TABLE recipient ADD COLUMN system_phone_type INTEGER DEFAULT -1");
+
+ String localNumber = TextSecurePreferences.getLocalNumber(context);
+ if (!TextUtils.isEmpty(localNumber)) {
+ try (Cursor cursor = db.query("recipient", null, "phone = ?", new String[] { localNumber }, null, null, null)) {
+ if (cursor == null || !cursor.moveToFirst()) {
+ ContentValues values = new ContentValues();
+ values.put("phone", localNumber);
+ values.put("registered", 1);
+ values.put("profile_sharing", 1);
+ values.put("signal_profile_name", TextSecurePreferences.getProfileName(context));
+ db.insert("recipient", null, values);
+ } else {
+ db.execSQL("UPDATE recipient SET registered = ?, profile_sharing = ?, signal_profile_name = ? WHERE phone = ?",
+ new String[] { "1", "1", TextSecurePreferences.getProfileName(context), localNumber });
+ }
+ }
+ }
+ }
+
db.setTransactionSuccessful();
} finally {
db.endTransaction();
diff --git a/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
index 3fd008f24f..fcc5836e1f 100644
--- a/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
+++ b/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
@@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.jobmanager.migrations.RecipientIdJobMigration;
import org.thoughtcrime.securesms.migrations.DatabaseMigrationJob;
import org.thoughtcrime.securesms.migrations.LegacyMigrationJob;
import org.thoughtcrime.securesms.migrations.MigrationCompleteJob;
+import org.thoughtcrime.securesms.migrations.RecipientSearchMigrationJob;
import java.util.Arrays;
import java.util.HashMap;
@@ -82,6 +83,7 @@ public final class JobManagerFactories {
put(DatabaseMigrationJob.KEY, new DatabaseMigrationJob.Factory());
put(LegacyMigrationJob.KEY, new LegacyMigrationJob.Factory());
put(MigrationCompleteJob.KEY, new MigrationCompleteJob.Factory());
+ put(RecipientSearchMigrationJob.KEY, new RecipientSearchMigrationJob.Factory());
// Dead jobs
put("PushContentReceiveJob", new FailingJob.Factory());
diff --git a/src/org/thoughtcrime/securesms/mediasend/CameraContactsRepository.java b/src/org/thoughtcrime/securesms/mediasend/CameraContactsRepository.java
index d4df95fb4e..64d376105f 100644
--- a/src/org/thoughtcrime/securesms/mediasend/CameraContactsRepository.java
+++ b/src/org/thoughtcrime/securesms/mediasend/CameraContactsRepository.java
@@ -7,8 +7,7 @@ import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
-import org.thoughtcrime.securesms.contacts.ContactsDatabase;
-import org.thoughtcrime.securesms.database.Address;
+import org.thoughtcrime.securesms.contacts.ContactRepository;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase;
@@ -32,15 +31,15 @@ class CameraContactsRepository {
private final Context context;
private final ThreadDatabase threadDatabase;
private final GroupDatabase groupDatabase;
- private final ContactsDatabase contactsDatabase;
private final RecipientDatabase recipientDatabase;
+ private final ContactRepository contactRepository;
CameraContactsRepository(@NonNull Context context) {
this.context = context.getApplicationContext();
this.threadDatabase = DatabaseFactory.getThreadDatabase(context);
this.groupDatabase = DatabaseFactory.getGroupDatabase(context);
- this.contactsDatabase = DatabaseFactory.getContactsDatabase(context);
this.recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
+ this.contactRepository = new ContactRepository(context);
}
void getCameraContacts(@NonNull Callback callback) {
@@ -80,9 +79,10 @@ class CameraContactsRepository {
private @NonNull List getContacts(@NonNull String query) {
List recipients = new ArrayList<>();
- try (Cursor cursor = contactsDatabase.queryTextSecureContacts(query)) {
+ try (Cursor cursor = contactRepository.querySignalContacts(query)) {
while (cursor.moveToNext()) {
- Recipient recipient = Recipient.external(context, cursor.getString(1));
+ RecipientId id = RecipientId.from(cursor.getLong(cursor.getColumnIndexOrThrow(ContactRepository.ID_COLUMN)));
+ Recipient recipient = Recipient.resolved(id);
recipients.add(recipient);
}
}
diff --git a/src/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java b/src/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java
index f5a8b554dc..0485ed7fd2 100644
--- a/src/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java
+++ b/src/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java
@@ -11,6 +11,7 @@ import com.annimon.stream.Stream;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
+import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.Util;
@@ -38,8 +39,9 @@ public class ApplicationMigrations {
private static final MutableLiveData UI_BLOCKING_MIGRATION_RUNNING = new MutableLiveData<>();
private static final class Version {
- static final int LEGACY = 455;
- static final int RECIPIENT_ID = 525; // TODO [greyson] USE PROPER APPLICATION VERSION
+ static final int LEGACY = 455;
+ static final int RECIPIENT_ID = 525; // TODO [greyson] USE PROPER APPLICATION VERSION
+ static final int RECIPIENT_SEARCH = 525; // TODO [greyson] USE PROPER APPLICATION VERSION
}
/**
@@ -133,6 +135,10 @@ public class ApplicationMigrations {
jobs.add(new DatabaseMigrationJob());
}
+ if (lastSeenVersion < Version.RECIPIENT_SEARCH) {
+ jobs.add(new RecipientSearchMigrationJob());
+ }
+
return jobs;
}
}
diff --git a/src/org/thoughtcrime/securesms/migrations/RecipientSearchMigrationJob.java b/src/org/thoughtcrime/securesms/migrations/RecipientSearchMigrationJob.java
new file mode 100644
index 0000000000..a90e7ac8ab
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/migrations/RecipientSearchMigrationJob.java
@@ -0,0 +1,54 @@
+package org.thoughtcrime.securesms.migrations;
+
+import androidx.annotation.NonNull;
+
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
+import org.thoughtcrime.securesms.util.DirectoryHelper;
+
+import java.io.IOException;
+
+/**
+ * We added a column for keeping track of the phone number type ("mobile", "home", etc) to the
+ * recipient database, and therefore we need to do a directory sync to fill in that column.
+ */
+public class RecipientSearchMigrationJob extends MigrationJob {
+
+ public static final String KEY = "RecipientSearchMigrationJob";
+
+ RecipientSearchMigrationJob() {
+ this(new Job.Parameters.Builder().addConstraint(NetworkConstraint.KEY).build());
+ }
+
+ private RecipientSearchMigrationJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
+ }
+
+ @Override
+ public @NonNull String getFactoryKey() {
+ return KEY;
+ }
+
+ @Override
+ boolean isUiBlocking() {
+ return false;
+ }
+
+ @Override
+ void performMigration() throws Exception {
+ DirectoryHelper.refreshDirectory(context, false);
+ }
+
+ @Override
+ boolean shouldRetry(@NonNull Exception e) {
+ return e instanceof IOException;
+ }
+
+ public static class Factory implements Job.Factory {
+ @Override
+ public @NonNull RecipientSearchMigrationJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new RecipientSearchMigrationJob(parameters);
+ }
+ }
+}
diff --git a/src/org/thoughtcrime/securesms/recipients/LiveRecipient.java b/src/org/thoughtcrime/securesms/recipients/LiveRecipient.java
index 113f90b7f9..172284f428 100644
--- a/src/org/thoughtcrime/securesms/recipients/LiveRecipient.java
+++ b/src/org/thoughtcrime/securesms/recipients/LiveRecipient.java
@@ -152,7 +152,7 @@ public final class LiveRecipient {
private @NonNull RecipientDetails getIndividualRecipientDetails(RecipientSettings settings) {
boolean systemContact = !TextUtils.isEmpty(settings.getSystemDisplayName());
boolean isLocalNumber = settings.getAddress().serialize().equals(TextSecurePreferences.getLocalNumber(context));
- return new RecipientDetails(null, Optional.absent(), systemContact, isLocalNumber, settings, null);
+ return new RecipientDetails(context, null, Optional.absent(), systemContact, isLocalNumber, settings, null);
}
@WorkerThread
@@ -172,10 +172,10 @@ public final class LiveRecipient {
avatarId = Optional.of(groupRecord.get().getAvatarId());
}
- return new RecipientDetails(title, avatarId, false, false, settings, members);
+ return new RecipientDetails(context, title, avatarId, false, false, settings, members);
}
- return new RecipientDetails(unnamedGroupName, Optional.absent(), false, false, settings, null);
+ return new RecipientDetails(context, unnamedGroupName, Optional.absent(), false, false, settings, null);
}
@Override
diff --git a/src/org/thoughtcrime/securesms/recipients/Recipient.java b/src/org/thoughtcrime/securesms/recipients/Recipient.java
index bb6a767f03..aee90cfa53 100644
--- a/src/org/thoughtcrime/securesms/recipients/Recipient.java
+++ b/src/org/thoughtcrime/securesms/recipients/Recipient.java
@@ -207,6 +207,20 @@ public class Recipient {
return this.name;
}
+ public @NonNull String getDisplayName() {
+ String name = getName();
+ if (!TextUtils.isEmpty(name)) {
+ return name;
+ }
+
+ String profileName = getProfileName();
+ if (!TextUtils.isEmpty(profileName)) {
+ return profileName;
+ }
+
+ return requireAddress().serialize();
+ }
+
public @NonNull MaterialColor getColor() {
if (isGroup()) return MaterialColor.GROUP;
else if (color != null) return color;
diff --git a/src/org/thoughtcrime/securesms/recipients/RecipientDetails.java b/src/org/thoughtcrime/securesms/recipients/RecipientDetails.java
index 3b83fd69ec..a9afda852c 100644
--- a/src/org/thoughtcrime/securesms/recipients/RecipientDetails.java
+++ b/src/org/thoughtcrime/securesms/recipients/RecipientDetails.java
@@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.recipients;
+import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
@@ -11,6 +12,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
@@ -33,7 +35,7 @@ public class RecipientDetails {
final VibrateState callVibrateState;
final boolean blocked;
final int expireMessages;
- final List participants;
+ final List participants;
final String profileName;
final boolean seenInviteReminder;
final Optional defaultSubscriptionId;
@@ -47,7 +49,8 @@ public class RecipientDetails {
final UnidentifiedAccessMode unidentifiedAccessMode;
final boolean forceSmsSelection;
- RecipientDetails(@Nullable String name,
+ RecipientDetails(@NonNull Context context,
+ @Nullable String name,
@NonNull Optional groupAvatarId,
boolean systemContact,
boolean isLocalNumber,
@@ -68,7 +71,7 @@ public class RecipientDetails {
this.blocked = settings.isBlocked();
this.expireMessages = settings.getExpireMessages();
this.participants = participants == null ? new LinkedList<>() : participants;
- this.profileName = settings.getProfileName();
+ this.profileName = isLocalNumber ? TextSecurePreferences.getProfileName(context) : settings.getProfileName();
this.seenInviteReminder = settings.hasSeenInviteReminder();
this.defaultSubscriptionId = settings.getDefaultSubscriptionId();
this.registered = settings.getRegistered();
diff --git a/src/org/thoughtcrime/securesms/search/SearchFragment.java b/src/org/thoughtcrime/securesms/search/SearchFragment.java
index d6f2e72dfe..5fd57053c5 100644
--- a/src/org/thoughtcrime/securesms/search/SearchFragment.java
+++ b/src/org/thoughtcrime/securesms/search/SearchFragment.java
@@ -16,6 +16,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
+import org.thoughtcrime.securesms.contacts.ContactRepository;
import org.thoughtcrime.securesms.conversation.ConversationActivity;
import org.thoughtcrime.securesms.ConversationListActivity;
import org.thoughtcrime.securesms.R;
@@ -67,8 +68,8 @@ public class SearchFragment extends Fragment implements SearchListAdapter.EventL
SearchRepository searchRepository = new SearchRepository(getContext(),
DatabaseFactory.getSearchDatabase(getContext()),
- DatabaseFactory.getContactsDatabase(getContext()),
DatabaseFactory.getThreadDatabase(getContext()),
+ new ContactRepository(requireContext()),
ContactAccessor.getInstance(),
SignalExecutors.SERIAL);
viewModel = ViewModelProviders.of(this, new SearchViewModel.Factory(searchRepository)).get(SearchViewModel.class);
diff --git a/src/org/thoughtcrime/securesms/search/SearchRepository.java b/src/org/thoughtcrime/securesms/search/SearchRepository.java
index 69e0bf1ef5..8bebb038b7 100644
--- a/src/org/thoughtcrime/securesms/search/SearchRepository.java
+++ b/src/org/thoughtcrime/securesms/search/SearchRepository.java
@@ -12,6 +12,7 @@ import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.contacts.ContactAccessor;
+import org.thoughtcrime.securesms.contacts.ContactRepository;
import org.thoughtcrime.securesms.contacts.ContactsDatabase;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.CursorList;
@@ -56,26 +57,26 @@ public class SearchRepository {
}
}
- private final Context context;
- private final SearchDatabase searchDatabase;
- private final ContactsDatabase contactsDatabase;
- private final ThreadDatabase threadDatabase;
- private final ContactAccessor contactAccessor;
- private final Executor executor;
+ private final Context context;
+ private final SearchDatabase searchDatabase;
+ private final ContactRepository contactRepository;
+ private final ThreadDatabase threadDatabase;
+ private final ContactAccessor contactAccessor;
+ private final Executor executor;
public SearchRepository(@NonNull Context context,
@NonNull SearchDatabase searchDatabase,
- @NonNull ContactsDatabase contactsDatabase,
@NonNull ThreadDatabase threadDatabase,
+ @NonNull ContactRepository contactRepository,
@NonNull ContactAccessor contactAccessor,
@NonNull Executor executor)
{
- this.context = context.getApplicationContext();
- this.searchDatabase = searchDatabase;
- this.contactsDatabase = contactsDatabase;
- this.threadDatabase = threadDatabase;
- this.contactAccessor = contactAccessor;
- this.executor = executor;
+ this.context = context.getApplicationContext();
+ this.searchDatabase = searchDatabase;
+ this.threadDatabase = threadDatabase;
+ this.contactRepository = contactRepository;
+ this.contactAccessor = contactAccessor;
+ this.executor = executor;
}
public void query(@NonNull String query, @NonNull Callback callback) {
@@ -125,8 +126,8 @@ public class SearchRepository {
return CursorList.emptyList();
}
- Cursor textSecureContacts = contactsDatabase.queryTextSecureContacts(query);
- Cursor systemContacts = contactsDatabase.querySystemContacts(query);
+ Cursor textSecureContacts = contactRepository.querySignalContacts(query);
+ Cursor systemContacts = contactRepository.queryNonSignalContacts(query);
MergeCursor contacts = new MergeCursor(new Cursor[]{ textSecureContacts, systemContacts });
return new CursorList<>(contacts, new RecipientModelBuilder(context));
diff --git a/src/org/thoughtcrime/securesms/util/DirectoryHelper.java b/src/org/thoughtcrime/securesms/util/DirectoryHelper.java
index 2be20e07c9..e856dc750a 100644
--- a/src/org/thoughtcrime/securesms/util/DirectoryHelper.java
+++ b/src/org/thoughtcrime/securesms/util/DirectoryHelper.java
@@ -205,11 +205,12 @@ public class DirectoryHelper {
String displayName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String contactPhotoUri = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
String contactLabel = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.LABEL));
+ int phoneType = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.TYPE));
Uri contactUri = ContactsContract.Contacts.getLookupUri(cursor.getLong(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone._ID)),
cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY)));
- handle.setSystemContactInfo(recipientId, displayName, contactPhotoUri, contactLabel, contactUri.toString());
+ handle.setSystemContactInfo(recipientId, displayName, contactPhotoUri, contactLabel, phoneType, contactUri.toString());
}
}
} finally {