Add mention detection to search flows.

This commit is contained in:
Cody Henthorne
2020-08-07 15:18:40 -04:00
committed by GitHub
parent 5cd4b82ed0
commit d563de4207
7 changed files with 323 additions and 56 deletions

View File

@@ -6,6 +6,9 @@ import android.database.Cursor;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.annimon.stream.Stream;
import net.sqlcipher.database.SQLiteDatabase;
@@ -15,7 +18,6 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.CursorUtil;
import org.thoughtcrime.securesms.util.SqlUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
@@ -86,27 +88,58 @@ public class MentionDatabase extends Database {
}
public @NonNull Map<Long, List<Mention>> getMentionsForMessages(@NonNull Collection<Long> messageIds) {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
Map<Long, List<Mention>> mentions = new HashMap<>();
String ids = TextUtils.join(",", messageIds);
SQLiteDatabase db = databaseHelper.getReadableDatabase();
String ids = TextUtils.join(",", messageIds);
try (Cursor cursor = db.query(TABLE_NAME, null, MESSAGE_ID + " IN (" + ids + ")", null, null, null, null)) {
while (cursor != null && cursor.moveToNext()) {
long messageId = CursorUtil.requireLong(cursor, MESSAGE_ID);
List<Mention> messageMentions = mentions.get(messageId);
return readMentions(cursor);
}
}
if (messageMentions == null) {
messageMentions = new LinkedList<>();
mentions.put(messageId, messageMentions);
}
public @NonNull Map<Long, List<Mention>> getMentionsContainingRecipients(@NonNull Collection<RecipientId> recipientIds, long limit) {
return getMentionsContainingRecipients(recipientIds, -1, limit);
}
messageMentions.add(new Mention(RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID)),
CursorUtil.requireInt(cursor, RANGE_START),
CursorUtil.requireInt(cursor, RANGE_LENGTH)));
}
public @NonNull Map<Long, List<Mention>> getMentionsContainingRecipients(@NonNull Collection<RecipientId> recipientIds, long threadId, long limit) {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
String ids = TextUtils.join(",", Stream.of(recipientIds).map(RecipientId::serialize).toList());
String where = " WHERE " + RECIPIENT_ID + " IN (" + ids + ")";
if (threadId != -1) {
where += " AND " + THREAD_ID + " = " + threadId;
}
String subSelect = "SELECT DISTINCT " + MESSAGE_ID +
" FROM " + TABLE_NAME +
where +
" ORDER BY " + ID + " DESC" +
" LIMIT " + limit;
String query = "SELECT *" +
" FROM " + TABLE_NAME +
" WHERE " + MESSAGE_ID +
" IN (" + subSelect + ")";
try (Cursor cursor = db.rawQuery(query, null)) {
return readMentions(cursor);
}
}
private @NonNull Map<Long, List<Mention>> readMentions(@Nullable Cursor cursor) {
Map<Long, List<Mention>> mentions = new HashMap<>();
while (cursor != null && cursor.moveToNext()) {
long messageId = CursorUtil.requireLong(cursor, MESSAGE_ID);
List<Mention> messageMentions = mentions.get(messageId);
if (messageMentions == null) {
messageMentions = new LinkedList<>();
mentions.put(messageId, messageMentions);
}
messageMentions.add(new Mention(RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID)),
CursorUtil.requireInt(cursor, RANGE_START),
CursorUtil.requireInt(cursor, RANGE_LENGTH)));
}
return mentions;
}
}

View File

@@ -470,6 +470,11 @@ public class MmsDatabase extends MessagingDatabase {
}
}
public Reader getMessages(Collection<Long> messageIds) {
String ids = TextUtils.join(",", messageIds);
return readerFor(rawQuery(MmsDatabase.TABLE_NAME + "." + MmsDatabase.ID + " IN (" + ids + ")", null));
}
public Reader getExpireStartedMessages() {
String where = EXPIRE_STARTED + " > 0";
return readerFor(rawQuery(where, null));

View File

@@ -1933,17 +1933,24 @@ public class RecipientDatabase extends Database {
return databaseHelper.getReadableDatabase().query(TABLE_NAME, SEARCH_PROJECTION, selection, args, null, null, null);
}
public @NonNull List<Recipient> queryRecipientsForMentions(@NonNull String query, @NonNull List<RecipientId> recipientIds) {
if (TextUtils.isEmpty(query) || recipientIds.isEmpty()) {
public @NonNull List<Recipient> queryRecipientsForMentions(@NonNull String query) {
return queryRecipientsForMentions(query, null);
}
public @NonNull List<Recipient> queryRecipientsForMentions(@NonNull String query, @Nullable List<RecipientId> recipientIds) {
if (TextUtils.isEmpty(query)) {
return Collections.emptyList();
}
query = buildCaseInsensitiveGlobPattern(query);
String ids = TextUtils.join(",", Stream.of(recipientIds).map(RecipientId::serialize).toList());
String ids = null;
if (Util.hasItems(recipientIds)) {
ids = TextUtils.join(",", Stream.of(recipientIds).map(RecipientId::serialize).toList());
}
String selection = BLOCKED + " = 0 AND " +
ID + " IN (" + ids + ") AND " +
(ids != null ? ID + " IN (" + ids + ") AND " : "") +
SORT_NAME + " GLOB ?";
List<Recipient> recipients = new ArrayList<>();

View File

@@ -26,6 +26,10 @@ public class SearchDatabase extends Database {
public static final String SNIPPET = "snippet";
public static final String CONVERSATION_RECIPIENT = "conversation_recipient";
public static final String MESSAGE_RECIPIENT = "message_recipient";
public static final String IS_MMS = "is_mms";
public static final String MESSAGE_ID = "message_id";
public static final String SNIPPET_WRAP = "...";
public static final String[] CREATE_TABLE = {
"CREATE VIRTUAL TABLE " + SMS_FTS_TABLE_NAME + " USING fts5(" + BODY + ", " + THREAD_ID + " UNINDEXED, content=" + SmsDatabase.TABLE_NAME + ", content_rowid=" + SmsDatabase.ID + ");",
@@ -60,9 +64,12 @@ public class SearchDatabase extends Database {
"SELECT " +
ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.RECIPIENT_ID + " AS " + CONVERSATION_RECIPIENT + ", " +
MmsSmsColumns.RECIPIENT_ID + " AS " + MESSAGE_RECIPIENT + ", " +
"snippet(" + SMS_FTS_TABLE_NAME + ", -1, '', '', '...', 7) AS " + SNIPPET + ", " +
"snippet(" + SMS_FTS_TABLE_NAME + ", -1, '', '', '" + SNIPPET_WRAP + "', 7) AS " + SNIPPET + ", " +
SmsDatabase.TABLE_NAME + "." + SmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + ", " +
SMS_FTS_TABLE_NAME + "." + THREAD_ID + " " +
SMS_FTS_TABLE_NAME + "." + THREAD_ID + ", " +
SMS_FTS_TABLE_NAME + "." + BODY + ", " +
SMS_FTS_TABLE_NAME + "." + ID + " AS " + MESSAGE_ID + ", " +
"0 AS " + IS_MMS + " " +
"FROM " + SmsDatabase.TABLE_NAME + " " +
"INNER JOIN " + SMS_FTS_TABLE_NAME + " ON " + SMS_FTS_TABLE_NAME + "." + ID + " = " + SmsDatabase.TABLE_NAME + "." + SmsDatabase.ID + " " +
"INNER JOIN " + ThreadDatabase.TABLE_NAME + " ON " + SMS_FTS_TABLE_NAME + "." + THREAD_ID + " = " + ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.ID + " " +
@@ -71,9 +78,12 @@ public class SearchDatabase extends Database {
"SELECT " +
ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.RECIPIENT_ID + " AS " + CONVERSATION_RECIPIENT + ", " +
MmsSmsColumns.RECIPIENT_ID + " AS " + MESSAGE_RECIPIENT + ", " +
"snippet(" + MMS_FTS_TABLE_NAME + ", -1, '', '', '...', 7) AS " + SNIPPET + ", " +
"snippet(" + MMS_FTS_TABLE_NAME + ", -1, '', '', '" + SNIPPET_WRAP + "', 7) AS " + SNIPPET + ", " +
MmsDatabase.TABLE_NAME + "." + MmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + ", " +
MMS_FTS_TABLE_NAME + "." + THREAD_ID + " " +
MMS_FTS_TABLE_NAME + "." + THREAD_ID + ", " +
MMS_FTS_TABLE_NAME + "." + BODY + ", " +
MMS_FTS_TABLE_NAME + "." + ID + " AS " + MESSAGE_ID + ", " +
"1 AS " + IS_MMS + " " +
"FROM " + MmsDatabase.TABLE_NAME + " " +
"INNER JOIN " + MMS_FTS_TABLE_NAME + " ON " + MMS_FTS_TABLE_NAME + "." + ID + " = " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.ID + " " +
"INNER JOIN " + ThreadDatabase.TABLE_NAME + " ON " + MMS_FTS_TABLE_NAME + "." + THREAD_ID + " = " + ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.ID + " " +
@@ -85,9 +95,12 @@ public class SearchDatabase extends Database {
"SELECT " +
ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.RECIPIENT_ID + " AS " + CONVERSATION_RECIPIENT + ", " +
MmsSmsColumns.RECIPIENT_ID + " AS " + MESSAGE_RECIPIENT + ", " +
"snippet(" + SMS_FTS_TABLE_NAME + ", -1, '', '', '...', 7) AS " + SNIPPET + ", " +
"snippet(" + SMS_FTS_TABLE_NAME + ", -1, '', '', '" + SNIPPET_WRAP + "', 7) AS " + SNIPPET + ", " +
SmsDatabase.TABLE_NAME + "." + SmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + ", " +
SMS_FTS_TABLE_NAME + "." + THREAD_ID + " " +
SMS_FTS_TABLE_NAME + "." + THREAD_ID + ", " +
SMS_FTS_TABLE_NAME + "." + BODY + ", " +
SMS_FTS_TABLE_NAME + "." + ID + " AS " + MESSAGE_ID + ", " +
"0 AS " + IS_MMS + " " +
"FROM " + SmsDatabase.TABLE_NAME + " " +
"INNER JOIN " + SMS_FTS_TABLE_NAME + " ON " + SMS_FTS_TABLE_NAME + "." + ID + " = " + SmsDatabase.TABLE_NAME + "." + SmsDatabase.ID + " " +
"INNER JOIN " + ThreadDatabase.TABLE_NAME + " ON " + SMS_FTS_TABLE_NAME + "." + THREAD_ID + " = " + ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.ID + " " +
@@ -96,9 +109,12 @@ public class SearchDatabase extends Database {
"SELECT " +
ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.RECIPIENT_ID + " AS " + CONVERSATION_RECIPIENT + ", " +
MmsSmsColumns.RECIPIENT_ID + " AS " + MESSAGE_RECIPIENT + ", " +
"snippet(" + MMS_FTS_TABLE_NAME + ", -1, '', '', '...', 7) AS " + SNIPPET + ", " +
"snippet(" + MMS_FTS_TABLE_NAME + ", -1, '', '', '" + SNIPPET_WRAP + "', 7) AS " + SNIPPET + ", " +
MmsDatabase.TABLE_NAME + "." + MmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + ", " +
MMS_FTS_TABLE_NAME + "." + THREAD_ID + " " +
MMS_FTS_TABLE_NAME + "." + THREAD_ID + ", " +
MMS_FTS_TABLE_NAME + "." + BODY + ", " +
MMS_FTS_TABLE_NAME + "." + ID + " AS " + MESSAGE_ID + ", " +
"1 AS " + IS_MMS + " " +
"FROM " + MmsDatabase.TABLE_NAME + " " +
"INNER JOIN " + MMS_FTS_TABLE_NAME + " ON " + MMS_FTS_TABLE_NAME + "." + ID + " = " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.ID + " " +
"INNER JOIN " + ThreadDatabase.TABLE_NAME + " ON " + MMS_FTS_TABLE_NAME + "." + THREAD_ID + " = " + ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.ID + " " +