Add recent chats to top of share list

This commit is contained in:
Moxie Marlinspike 2017-11-16 15:21:46 -08:00
parent c5a9f27c31
commit cf81815bf6
14 changed files with 258 additions and 87 deletions

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<padding android:top="1dp" android:right="0dp" android:bottom="0dp" android:left="0dp" />
<solid android:color="#101010" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="0dp" android:bottom="0dp" android:left="0dp" />
<solid android:color="#222222" />
<size android:height="20dp"/>
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<padding android:top="1dp" android:right="0dp" android:bottom="0dp" android:left="0dp" />
<solid android:color="#d4d4d4" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="0dp" android:bottom="0dp" android:left="0dp" />
<solid android:color="@color/gray5" />
<size android:height="20dp"/>
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/contact_list_divider">
<TextView android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
android:paddingStart="16dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:textSize="14sp"
android:textColor="@color/signal_primary_dark"
tools:text="Recent chats"/>
</LinearLayout>

View File

@ -13,7 +13,6 @@
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="4dp"
android:clipToPadding="false"
android:scrollbars="vertical" />

View File

@ -132,6 +132,8 @@
<attr name="search_toolbar_background" format="color"/>
<attr name="contact_list_divider" format="reference"/>
<declare-styleable name="ColorPreference">
<attr name="itemLayout" format="reference" />
<attr name="choices" format="reference" />

View File

@ -1249,6 +1249,8 @@
<string name="UnauthorizedReminder_device_no_longer_registered">Device no longer registered</string>
<string name="UnauthorizedReminder_this_is_likely_because_you_registered_your_phone_number_with_Signal_on_a_different_device">This is likely because you registered your phone number with Signal on a different device. Tap to re-register.</string>
<string name="OutdatedBuildReminder_no_web_browser_installed">No web browser installed!</string>
<string name="ContactsCursorLoader_recent_chats">Recent chats</string>
<string name="ContactsCursorLoader_contacts">Contacts</string>
<!-- EOF -->

View File

@ -143,6 +143,8 @@
<item name="conversation_number_picker_text_color_normal">@color/gray65</item>
<item name="conversation_number_picker_text_color_selected">@color/black</item>
<item name="contact_list_divider">@drawable/contact_list_divider_light</item>
<item name="verification_background">@color/gray5</item>
<item name="emoji_tab_strip_background">@color/gray12</item>
@ -256,6 +258,8 @@
<item name="conversation_item_last_seen_background">#66333333</item>
<item name="conversation_item_last_seen_text_background">@drawable/last_seen_divider_text_background_dark</item>
<item name="contact_list_divider">@drawable/contact_list_divider_dark</item>
<item name="verification_background">#ff333333</item>
<item name="dialog_info_icon">@drawable/ic_info_outline_dark</item>

View File

@ -38,12 +38,13 @@ import org.thoughtcrime.securesms.contacts.ContactSelectionListItem;
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader;
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Fragment for selecting a one or more contacts from a list.
@ -54,11 +55,13 @@ import java.util.Map;
public class ContactSelectionListFragment extends Fragment
implements LoaderManager.LoaderCallbacks<Cursor>
{
@SuppressWarnings("unused")
private static final String TAG = ContactSelectionListFragment.class.getSimpleName();
public final static String DISPLAY_MODE = "display_mode";
public final static String MULTI_SELECT = "multi_select";
public final static String REFRESHABLE = "refreshable";
public static final String DISPLAY_MODE = "display_mode";
public static final String MULTI_SELECT = "multi_select";
public static final String REFRESHABLE = "refreshable";
public static final String RECENTS = "recents";
public final static int DISPLAY_MODE_ALL = ContactsCursorLoader.MODE_ALL;
public final static int DISPLAY_MODE_PUSH_ONLY = ContactsCursorLoader.MODE_PUSH_ONLY;
@ -66,7 +69,7 @@ public class ContactSelectionListFragment extends Fragment
private TextView emptyText;
private Map<Long, String> selectedContacts;
private Set<String> selectedContacts;
private OnContactSelectedListener onContactSelectedListener;
private SwipeRefreshLayout swipeRefresh;
private String cursorFilter;
@ -108,7 +111,7 @@ public class ContactSelectionListFragment extends Fragment
public @NonNull List<String> getSelectedContacts() {
List<String> selected = new LinkedList<>();
if (selectedContacts != null) {
selected.addAll(selectedContacts.values());
selected.addAll(selectedContacts);
}
return selected;
@ -151,9 +154,9 @@ public class ContactSelectionListFragment extends Fragment
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new ContactsCursorLoader(getActivity(),
return new ContactsCursorLoader(getActivity(), KeyCachingService.getMasterSecret(getContext()),
getActivity().getIntent().getIntExtra(DISPLAY_MODE, DISPLAY_MODE_ALL),
cursorFilter);
cursorFilter, getActivity().getIntent().getBooleanExtra(RECENTS, false));
}
@Override
@ -177,13 +180,12 @@ public class ContactSelectionListFragment extends Fragment
private class ListClickListener implements ContactSelectionListAdapter.ItemClickListener {
@Override
public void onItemClick(ContactSelectionListItem contact) {
if (!isMulti() || !selectedContacts.containsKey(contact.getContactId())) {
selectedContacts.put(contact.getContactId(), contact.getNumber());
if (!isMulti() || !selectedContacts.contains(contact.getNumber())) {
selectedContacts.add(contact.getNumber());
contact.setChecked(true);
if (onContactSelectedListener != null) onContactSelectedListener.onContactSelected(contact.getNumber());
} else {
selectedContacts.remove(contact.getContactId());
selectedContacts.remove(contact.getNumber());
contact.setChecked(false);
if (onContactSelectedListener != null) onContactSelectedListener.onContactDeselected(contact.getNumber());
}

View File

@ -100,6 +100,9 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
: ContactSelectionListFragment.DISPLAY_MODE_PUSH_ONLY);
}
getIntent().putExtra(ContactSelectionListFragment.REFRESHABLE, false);
getIntent().putExtra(ContactSelectionListFragment.RECENTS, true);
setContentView(R.layout.share_activity);
initializeToolbar();

View File

@ -43,7 +43,9 @@ import org.thoughtcrime.securesms.util.StickyHeaderDecoration.StickyHeaderAdapte
import org.thoughtcrime.securesms.util.Util;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* List adapter to display all contacts and their related information
@ -56,6 +58,9 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
{
private final static String TAG = ContactSelectionListAdapter.class.getSimpleName();
private static final int VIEW_TYPE_CONTACT = 0;
private static final int VIEW_TYPE_DIVIDER = 1;
private final static int STYLE_ATTRIBUTES[] = new int[]{R.attr.contact_selection_push_user,
R.attr.contact_selection_lay_user};
@ -65,10 +70,21 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
private final ItemClickListener clickListener;
private final GlideRequests glideRequests;
private final HashMap<Long, String> selectedContacts = new HashMap<>();
private final Set<String> selectedContacts = new HashSet<>();
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(@NonNull final View itemView,
public abstract static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
public abstract void bind(@NonNull GlideRequests glideRequests, int type, String name, String number, String label, int color, boolean multiSelect);
public abstract void unbind(@NonNull GlideRequests glideRequests);
public abstract void setChecked(boolean checked);
}
public static class ContactViewHolder extends ViewHolder {
ContactViewHolder(@NonNull final View itemView,
@Nullable final ItemClickListener clickListener)
{
super(itemView);
@ -80,10 +96,45 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
public ContactSelectionListItem getView() {
return (ContactSelectionListItem) itemView;
}
public void bind(@NonNull GlideRequests glideRequests, int type, String name, String number, String label, int color, boolean multiSelect) {
getView().set(glideRequests, type, name, number, label, color, multiSelect);
}
@Override
public void unbind(@NonNull GlideRequests glideRequests) {
getView().unbind(glideRequests);
}
@Override
public void setChecked(boolean checked) {
getView().setChecked(checked);
}
}
public static class HeaderViewHolder extends RecyclerView.ViewHolder {
public HeaderViewHolder(View itemView) {
public static class DividerViewHolder extends ViewHolder {
private final TextView label;
DividerViewHolder(View itemView) {
super(itemView);
this.label = itemView.findViewById(R.id.label);
}
@Override
public void bind(@NonNull GlideRequests glideRequests, int type, String name, String number, String label, int color, boolean multiSelect) {
this.label.setText(name);
}
@Override
public void unbind(@NonNull GlideRequests glideRequests) {}
@Override
public void setChecked(boolean checked) {}
}
static class HeaderViewHolder extends RecyclerView.ViewHolder {
HeaderViewHolder(View itemView) {
super(itemView);
}
}
@ -106,17 +157,23 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
public long getHeaderId(int i) {
if (!isActiveCursor()) return -1;
return Util.hashCode(getHeaderString(i), isPush(i));
int contactType = getContactType(i);
if (contactType == ContactsDatabase.DIVIDER_TYPE) return -1;
return Util.hashCode(getHeaderString(i), getContactType(i));
}
@Override
public ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(li.inflate(R.layout.contact_selection_list_item, parent, false), clickListener);
if (viewType == VIEW_TYPE_CONTACT) {
return new ContactViewHolder(li.inflate(R.layout.contact_selection_list_item, parent, false), clickListener);
} else {
return new DividerViewHolder(li.inflate(R.layout.contact_selection_list_divider, parent, false));
}
}
@Override
public void onBindItemViewHolder(ViewHolder viewHolder, @NonNull Cursor cursor) {
long id = cursor.getLong(cursor.getColumnIndexOrThrow(ContactsDatabase.ID_COLUMN));
int contactType = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.CONTACT_TYPE_COLUMN));
String name = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NAME_COLUMN));
String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_COLUMN));
@ -128,11 +185,21 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
int color = (contactType == ContactsDatabase.PUSH_TYPE) ? drawables.getColor(0, 0xa0000000) :
drawables.getColor(1, 0xff000000);
viewHolder.getView().unbind(glideRequests);
viewHolder.getView().set(glideRequests, id, contactType, name, number, labelText, color, multiSelect);
viewHolder.getView().setChecked(selectedContacts.containsKey(id));
viewHolder.unbind(glideRequests);
viewHolder.bind(glideRequests, contactType, name, number, labelText, color, multiSelect);
viewHolder.setChecked(selectedContacts.contains(number));
}
@Override
public int getItemViewType(@NonNull Cursor cursor) {
if (cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.CONTACT_TYPE_COLUMN)) == ContactsDatabase.DIVIDER_TYPE) {
return VIEW_TYPE_DIVIDER;
} else {
return VIEW_TYPE_CONTACT;
}
}
@Override
public HeaderViewHolder onCreateHeaderViewHolder(ViewGroup parent) {
return new HeaderViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.contact_selection_recyclerview_header, parent, false));
@ -145,7 +212,7 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
@Override
public void onItemViewRecycled(ViewHolder holder) {
holder.getView().unbind(glideRequests);
holder.unbind(glideRequests);
}
@Override
@ -153,7 +220,7 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
return getHeaderString(position);
}
public Map<Long, String> getSelectedContacts() {
public Set<String> getSelectedContacts() {
return selectedContacts;
}
@ -169,8 +236,15 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
}
private @NonNull String getHeaderString(int position) {
int contactType = getContactType(position);
if (contactType == ContactsDatabase.RECENT_TYPE || contactType == ContactsDatabase.DIVIDER_TYPE) {
return " ";
}
Cursor cursor = getCursorAtPositionOrThrow(position);
String letter = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NAME_COLUMN));
if (!TextUtils.isEmpty(letter)) {
String firstChar = letter.trim().substring(0, 1).toUpperCase();
if (Character.isLetterOrDigit(firstChar.codePointAt(0))) {
@ -181,9 +255,13 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
return "#";
}
private boolean isPush(int position) {
private int getContactType(int position) {
final Cursor cursor = getCursorAtPositionOrThrow(position);
return cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.CONTACT_TYPE_COLUMN)) == ContactsDatabase.PUSH_TYPE;
return cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.CONTACT_TYPE_COLUMN));
}
private boolean isPush(int position) {
return getContactType(position) == ContactsDatabase.PUSH_TYPE;
}
public interface ItemClickListener {

View File

@ -12,7 +12,6 @@ import android.widget.TextView;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.mms.GlideRequest;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
@ -21,6 +20,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
public class ContactSelectionListItem extends LinearLayout implements RecipientModifiedListener {
@SuppressWarnings("unused")
private static final String TAG = ContactSelectionListItem.class.getSimpleName();
private AvatarImageView contactPhotoImage;
@ -29,7 +29,6 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientM
private TextView labelView;
private CheckBox checkBox;
private long id;
private String number;
private Recipient recipient;
private GlideRequests glideRequests;
@ -54,9 +53,8 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientM
ViewUtil.setTextViewGravityStart(this.nameView, getContext());
}
public void set(@NonNull GlideRequests glideRequests, long id, int type, String name, String number, String label, int color, boolean multiSelect) {
public void set(@NonNull GlideRequests glideRequests, int type, String name, String number, String label, int color, boolean multiSelect) {
this.glideRequests = glideRequests;
this.id = id;
this.number = number;
if (type == ContactsDatabase.NEW_TYPE) {
@ -114,10 +112,6 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientM
this.nameView.setText(name);
}
public long getContactId() {
return id;
}
public String getNumber() {
return number;
}

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2013 Open Whisper Systems
/*
* Copyright (C) 2013-2017 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -27,9 +27,13 @@ import android.text.TextUtils;
import android.util.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.crypto.MasterCipher;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.NumberUtil;
@ -44,24 +48,59 @@ public class ContactsCursorLoader extends CursorLoader {
private static final String TAG = ContactsCursorLoader.class.getSimpleName();
public final static int MODE_ALL = 0;
public final static int MODE_PUSH_ONLY = 1;
public final static int MODE_SMS_ONLY = 2;
public static final int MODE_ALL = 0;
public static final int MODE_PUSH_ONLY = 1;
public static final int MODE_SMS_ONLY = 2;
private final String filter;
private final int mode;
private static final String[] CONTACT_PROJECTION = new String[]{ContactsDatabase.NAME_COLUMN,
ContactsDatabase.NUMBER_COLUMN,
ContactsDatabase.NUMBER_TYPE_COLUMN,
ContactsDatabase.LABEL_COLUMN,
ContactsDatabase.CONTACT_TYPE_COLUMN};
public ContactsCursorLoader(Context context, int mode, String filter) {
private final MasterSecret masterSecret;
private final String filter;
private final int mode;
private final boolean recents;
public ContactsCursorLoader(@NonNull Context context, @NonNull MasterSecret masterSecret,
int mode, String filter, boolean recents)
{
super(context);
this.filter = filter;
this.mode = mode;
this.masterSecret = masterSecret;
this.filter = filter;
this.mode = mode;
this.recents = recents;
}
@Override
public Cursor loadInBackground() {
ContactsDatabase contactsDatabase = DatabaseFactory.getContactsDatabase(getContext());
ArrayList<Cursor> cursorList = new ArrayList<>(3);
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(getContext());
ArrayList<Cursor> cursorList = new ArrayList<>(4);
if (recents && TextUtils.isEmpty(filter)) {
try (Cursor recentConversations = DatabaseFactory.getThreadDatabase(getContext()).getRecentConversationList(5)) {
MatrixCursor synthesizedContacts = new MatrixCursor(CONTACT_PROJECTION);
synthesizedContacts.addRow(new Object[] {getContext().getString(R.string.ContactsCursorLoader_recent_chats), "", ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE, "", ContactsDatabase.DIVIDER_TYPE});
ThreadDatabase.Reader reader = threadDatabase.readerFor(recentConversations, new MasterCipher(masterSecret));
ThreadRecord threadRecord;
while ((threadRecord = reader.getNext()) != null) {
synthesizedContacts.addRow(new Object[] {threadRecord.getRecipient().toShortString(),
threadRecord.getRecipient().getAddress().serialize(),
ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE,
"", ContactsDatabase.RECENT_TYPE});
}
synthesizedContacts.addRow(new Object[] {getContext().getString(R.string.ContactsCursorLoader_contacts), "", ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE, "", ContactsDatabase.DIVIDER_TYPE});
if (synthesizedContacts.getCount() > 2) cursorList.add(synthesizedContacts);
}
}
if (mode != MODE_SMS_ONLY) {
cursorList.add(contactsDatabase.queryTextSecureContacts(filter));
@ -74,14 +113,9 @@ public class ContactsCursorLoader extends CursorLoader {
}
if (!TextUtils.isEmpty(filter) && NumberUtil.isValidSmsOrEmail(filter)) {
MatrixCursor newNumberCursor = new MatrixCursor(new String[] {ContactsDatabase.ID_COLUMN,
ContactsDatabase.NAME_COLUMN,
ContactsDatabase.NUMBER_COLUMN,
ContactsDatabase.NUMBER_TYPE_COLUMN,
ContactsDatabase.LABEL_COLUMN,
ContactsDatabase.CONTACT_TYPE_COLUMN}, 1);
MatrixCursor newNumberCursor = new MatrixCursor(CONTACT_PROJECTION, 1);
newNumberCursor.addRow(new Object[] {-1L, getContext().getString(R.string.contact_selection_list__unknown_contact),
newNumberCursor.addRow(new Object[] {getContext().getString(R.string.contact_selection_list__unknown_contact),
filter, ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM,
"\u21e2", ContactsDatabase.NEW_TYPE});
@ -94,19 +128,13 @@ public class ContactsCursorLoader extends CursorLoader {
private @NonNull Cursor filterNonPushContacts(@NonNull Cursor cursor) {
try {
final long startMillis = System.currentTimeMillis();
final MatrixCursor matrix = new MatrixCursor(new String[]{ContactsDatabase.ID_COLUMN,
ContactsDatabase.NAME_COLUMN,
ContactsDatabase.NUMBER_COLUMN,
ContactsDatabase.NUMBER_TYPE_COLUMN,
ContactsDatabase.LABEL_COLUMN,
ContactsDatabase.CONTACT_TYPE_COLUMN});
final MatrixCursor matrix = new MatrixCursor(CONTACT_PROJECTION);
while (cursor.moveToNext()) {
final String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_COLUMN));
final Recipient recipient = Recipient.from(getContext(), Address.fromExternal(getContext(), number), false);
if (recipient.resolve().getRegistered() != RecipientDatabase.RegisteredState.REGISTERED) {
matrix.addRow(new Object[]{cursor.getLong(cursor.getColumnIndexOrThrow(ContactsDatabase.ID_COLUMN)),
cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NAME_COLUMN)),
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)),

View File

@ -62,16 +62,17 @@ 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 ID_COLUMN = "_id";
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 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;
@ -142,8 +143,7 @@ public class ContactsDatabase {
uri = uri.buildUpon().appendQueryParameter(ContactsContract.REMOVE_DUPLICATE_ENTRIES, "true").build();
}
String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone._ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.LABEL};
@ -151,7 +151,6 @@ public class ContactsDatabase {
String sort = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
Map<String, String> projectionMap = new HashMap<String, String>() {{
put(ID_COLUMN, ContactsContract.CommonDataKinds.Phone._ID);
put(NAME_COLUMN, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
put(NUMBER_COLUMN, ContactsContract.CommonDataKinds.Phone.NUMBER);
put(NUMBER_TYPE_COLUMN, ContactsContract.CommonDataKinds.Phone.TYPE);
@ -180,14 +179,12 @@ public class ContactsDatabase {
}
@NonNull Cursor queryTextSecureContacts(String filter) {
String[] projection = new String[] {ContactsContract.Data._ID,
ContactsContract.Contacts.DISPLAY_NAME,
String[] projection = new String[] {ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Data.DATA1};
String sort = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
Map<String, String> projectionMap = new HashMap<String, String>(){{
put(ID_COLUMN, ContactsContract.Data._ID);
put(NAME_COLUMN, ContactsContract.Contacts.DISPLAY_NAME);
put(NUMBER_COLUMN, ContactsContract.Data.DATA1);
}};

View File

@ -288,16 +288,6 @@ public class ThreadDatabase extends Database {
}};
}
// public void setUnread(long threadId, int unreadCount) {
// ContentValues contentValues = new ContentValues(1);
// contentValues.put(READ, 0);
// contentValues.put(UNREAD_COUNT, unreadCount);
//
// SQLiteDatabase db = databaseHelper.getWritableDatabase();
// db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {threadId + ""});
// notifyConversationListListeners();
// }
public void incrementUnread(long threadId, int amount) {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
db.execSQL("UPDATE " + TABLE_NAME + " SET " + READ + " = 0, " +
@ -351,7 +341,7 @@ public class ThreadDatabase extends Database {
selectionArgs[i++] = DelimiterUtil.escape(address.serialize(), ' ');
}
String query = createQuery(selection);
String query = createQuery(selection, 0);
cursors.add(db.rawQuery(query, selectionArgs));
}
@ -360,6 +350,13 @@ public class ThreadDatabase extends Database {
return cursor;
}
public Cursor getRecentConversationList(int limit) {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
String query = createQuery(MESSAGE_COUNT + " != 0", limit);
return db.rawQuery(query, null);
}
public Cursor getConversationList() {
return getConversationList("0");
}
@ -370,7 +367,7 @@ public class ThreadDatabase extends Database {
private Cursor getConversationList(String archived) {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
String query = createQuery(ARCHIVED + " = ? AND " + MESSAGE_COUNT + " != 0");
String query = createQuery(ARCHIVED + " = ? AND " + MESSAGE_COUNT + " != 0", 0);
Cursor cursor = db.rawQuery(query, new String[]{archived});
setNotifyConverationListListeners(cursor);
@ -380,7 +377,7 @@ public class ThreadDatabase extends Database {
public Cursor getDirectShareList() {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
String query = createQuery(MESSAGE_COUNT + " != 0");
String query = createQuery(MESSAGE_COUNT + " != 0", 0);
return db.rawQuery(query, null);
}
@ -598,15 +595,22 @@ public class ThreadDatabase extends Database {
return thumbnail != null ? thumbnail.getThumbnailUri() : null;
}
private @NonNull String createQuery(@NonNull String where) {
private @NonNull String createQuery(@NonNull String where, int limit) {
String projection = Util.join(COMBINED_THREAD_RECIPIENT_GROUP_PROJECTION, ",");
return "SELECT " + projection + " FROM " + TABLE_NAME +
String query =
"SELECT " + projection + " FROM " + TABLE_NAME +
" LEFT OUTER JOIN " + RecipientDatabase.TABLE_NAME +
" ON " + TABLE_NAME + "." + ADDRESS + " = " + RecipientDatabase.TABLE_NAME + "." + RecipientDatabase.ADDRESS +
" LEFT OUTER JOIN " + GroupDatabase.TABLE_NAME +
" ON " + TABLE_NAME + "." + ADDRESS + " = " + GroupDatabase.TABLE_NAME + "." + GroupDatabase.GROUP_ID +
" WHERE " + where +
" ORDER BY " + TABLE_NAME + "." + DATE + " DESC";
if (limit > 0) {
query += " LIMIT " + limit;
}
return query;
}
public interface ProgressListener {