Skip to content

Commit

Permalink
Sort "new group story" entries by recency.
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-signal authored and cody-signal committed Aug 18, 2022
1 parent 28310a8 commit e517232
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 6 deletions.
Expand Up @@ -63,6 +63,7 @@ class ContactSearchConfiguration private constructor(
val includeV1: Boolean = false,
val includeInactive: Boolean = false,
val returnAsGroupStories: Boolean = false,
val sortOrder: ContactSearchSortOrder = ContactSearchSortOrder.NATURAL,
override val includeHeader: Boolean,
override val expandConfig: ExpandConfig? = null
) : Section(SectionKey.GROUPS)
Expand Down
Expand Up @@ -41,8 +41,19 @@ open class ContactSearchPagedDataSourceRepository(
return contactRepository.queryNonGroupContacts(query ?: "", includeSelf)
}

open fun getGroupContacts(section: ContactSearchConfiguration.Section.Groups, query: String?): Cursor? {
return SignalDatabase.groups.queryGroupsByTitle(query ?: "", section.includeInactive, !section.includeV1, !section.includeMms).cursor
open fun getGroupContacts(
section: ContactSearchConfiguration.Section.Groups,
query: String?
): Cursor? {
return SignalDatabase.groups.queryGroups(
GroupDatabase.GroupQuery.Builder()
.withSearchQuery(query)
.withInactiveGroups(section.includeInactive)
.withMmsGroups(section.includeMms)
.withV1Groups(section.includeV1)
.withSortOrder(section.sortOrder)
.build()
).cursor
}

open fun getRecents(section: ContactSearchConfiguration.Section.Recents): Cursor? {
Expand Down
@@ -0,0 +1,19 @@
package org.thoughtcrime.securesms.contacts.paged

/**
* Different options for sort order of contact search items.
*/
enum class ContactSearchSortOrder {
/**
* The "natural" expected order. This is considered the default ordering.
* For example, Groups would normally be ordered by title from A-Z.
*/
NATURAL,

/**
* The requested ordering is by recency. This can mean different things for
* different contact types. For example, for Groups, this entry means that
* the results are ordered by latest message date in descending order.
*/
RECENCY
}
Expand Up @@ -24,6 +24,7 @@
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
import org.signal.storageservice.protos.groups.local.EnabledState;
import org.thoughtcrime.securesms.contacts.paged.ContactSearchSortOrder;
import org.thoughtcrime.securesms.crypto.SenderKeyUtil;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.BadGroupIdException;
Expand Down Expand Up @@ -287,6 +288,31 @@ public boolean isUnknownGroup(@NonNull GroupId groupId) {
}

public Reader queryGroupsByTitle(String inputQuery, boolean includeInactive, boolean excludeV1, boolean excludeMms) {
SqlUtil.Query query = getGroupQueryWhereStatement(inputQuery, includeInactive, excludeV1, excludeMms);
Cursor cursor = databaseHelper.getSignalReadableDatabase().query(TABLE_NAME, null, query.getWhere(), query.getWhereArgs(), null, null, TITLE + " COLLATE NOCASE ASC");

return new Reader(cursor);
}

public Reader queryGroupsByRecency(@NonNull GroupQuery groupQuery) {
SqlUtil.Query query = getGroupQueryWhereStatement(groupQuery.searchQuery, groupQuery.includeInactive, !groupQuery.includeV1, !groupQuery.includeMms);
String sql = "SELECT * FROM " + TABLE_NAME +
" LEFT JOIN " + ThreadDatabase.TABLE_NAME + " ON " + RECIPIENT_ID + " = " + ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.RECIPIENT_ID +
" WHERE " + query.getWhere() +
" ORDER BY " + ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.DATE + " DESC";

return new Reader(databaseHelper.getSignalReadableDatabase().rawQuery(sql, query.getWhereArgs()));
}

public Reader queryGroups(@NonNull GroupQuery groupQuery) {
if (groupQuery.sortOrder == ContactSearchSortOrder.NATURAL) {
return queryGroupsByTitle(groupQuery.searchQuery, groupQuery.includeInactive, !groupQuery.includeV1, !groupQuery.includeMms);
} else {
return queryGroupsByRecency(groupQuery);
}
}

private @NonNull SqlUtil.Query getGroupQueryWhereStatement(String inputQuery, boolean includeInactive, boolean excludeV1, boolean excludeMms) {
String query;
String[] queryArgs;

Expand All @@ -308,9 +334,7 @@ public Reader queryGroupsByTitle(String inputQuery, boolean includeInactive, boo
query += " AND " + MMS + " = 0";
}

Cursor cursor = databaseHelper.getSignalReadableDatabase().query(TABLE_NAME, null, query, queryArgs, null, null, TITLE + " COLLATE NOCASE ASC");

return new Reader(cursor);
return new SqlUtil.Query(query, queryArgs);
}

public @NonNull DistributionId getOrCreateDistributionId(@NonNull GroupId.V2 groupId) {
Expand Down Expand Up @@ -1445,6 +1469,59 @@ public boolean isInGroup() {
}
}

public static class GroupQuery {
private final String searchQuery;
private final boolean includeInactive;
private final boolean includeV1;
private final boolean includeMms;
private final ContactSearchSortOrder sortOrder;

private GroupQuery(@NonNull Builder builder) {
this.searchQuery = builder.searchQuery;
this.includeInactive = builder.includeInactive;
this.includeV1 = builder.includeV1;
this.includeMms = builder.includeMms;
this.sortOrder = builder.sortOrder;
}

public static class Builder {
private String searchQuery = "";
private boolean includeInactive = false;
private boolean includeV1 = false;
private boolean includeMms = false;
private ContactSearchSortOrder sortOrder = ContactSearchSortOrder.NATURAL;

public @NonNull Builder withSearchQuery(@Nullable String query) {
this.searchQuery = TextUtils.isEmpty(query) ? "" : query;
return this;
}

public @NonNull Builder withInactiveGroups(boolean includeInactive) {
this.includeInactive = includeInactive;
return this;
}

public @NonNull Builder withV1Groups(boolean includeV1Groups) {
this.includeV1 = includeV1Groups;
return this;
}

public @NonNull Builder withMmsGroups(boolean includeMmsGroups) {
this.includeMms = includeMmsGroups;
return this;
}

public @NonNull Builder withSortOrder(@NonNull ContactSearchSortOrder sortOrder) {
this.sortOrder = sortOrder;
return this;
}

public GroupQuery build() {
return new GroupQuery(this);
}
}
}

public static class LegacyGroupInsertException extends IllegalStateException {
public LegacyGroupInsertException(@Nullable GroupId id) {
super("Tried to create a new GV1 entry when we already had a migrated GV2! " + id);
Expand Down
Expand Up @@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.components.FixedRoundedCornerBottomSheetDialog
import org.thoughtcrime.securesms.contacts.paged.ContactSearchConfiguration
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
import org.thoughtcrime.securesms.contacts.paged.ContactSearchMediator
import org.thoughtcrime.securesms.contacts.paged.ContactSearchSortOrder
import org.thoughtcrime.securesms.sharing.ShareContact
import org.thoughtcrime.securesms.sharing.ShareSelectionAdapter
import org.thoughtcrime.securesms.sharing.ShareSelectionMappingModel
Expand Down Expand Up @@ -73,7 +74,8 @@ class ChooseGroupStoryBottomSheet : FixedRoundedCornerBottomSheetDialogFragment(
addSection(
ContactSearchConfiguration.Section.Groups(
includeHeader = false,
returnAsGroupStories = true
returnAsGroupStories = true,
sortOrder = ContactSearchSortOrder.RECENCY
)
)
}
Expand Down

0 comments on commit e517232

Please sign in to comment.