Allow consecutive voice notes to be played as a playlist.

This commit is contained in:
Alex Hart
2020-10-15 13:55:08 -03:00
committed by Greyson Parrelli
parent 837ed76f85
commit 9a1c869efe
24 changed files with 485 additions and 87 deletions

View File

@@ -145,6 +145,9 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
abstract void deleteAllThreads();
abstract void deleteAbandonedMessages();
public abstract List<MessageRecord> getMessagesInThreadBeforeExclusive(long threadId, long timestamp, long limit);
public abstract List<MessageRecord> getMessagesInThreadAfterInclusive(long threadId, long timestamp, long limit);
public abstract SQLiteDatabase beginTransaction();
public abstract void endTransaction(SQLiteDatabase database);
public abstract void setTransactionSuccessful();

View File

@@ -82,6 +82,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -605,11 +606,25 @@ public class MmsDatabase extends MessageDatabase {
}
private Cursor rawQuery(@NonNull String where, @Nullable String[] arguments) {
return rawQuery(where, arguments, false, 0);
}
private Cursor rawQuery(@NonNull String where, @Nullable String[] arguments, boolean reverse, long limit) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
return database.rawQuery("SELECT " + Util.join(MMS_PROJECTION, ",") +
" FROM " + MmsDatabase.TABLE_NAME + " LEFT OUTER JOIN " + AttachmentDatabase.TABLE_NAME +
" ON (" + MmsDatabase.TABLE_NAME + "." + MmsDatabase.ID + " = " + AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.MMS_ID + ")" +
" WHERE " + where + " GROUP BY " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.ID, arguments);
String rawQueryString = "SELECT " + Util.join(MMS_PROJECTION, ",") +
" FROM " + MmsDatabase.TABLE_NAME + " LEFT OUTER JOIN " + AttachmentDatabase.TABLE_NAME +
" ON (" + MmsDatabase.TABLE_NAME + "." + MmsDatabase.ID + " = " + AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.MMS_ID + ")" +
" WHERE " + where + " GROUP BY " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.ID;
if (reverse) {
rawQueryString += " ORDER BY " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.ID + " DESC";
}
if (limit > 0) {
rawQueryString += " LIMIT " + limit;
}
return database.rawQuery(rawQueryString, arguments);
}
private Cursor internalGetMessage(long messageId) {
@@ -1603,6 +1618,40 @@ public class MmsDatabase extends MessageDatabase {
db.delete(TABLE_NAME, where, null);
}
@Override
public List<MessageRecord> getMessagesInThreadBeforeExclusive(long threadId, long timestamp, long limit) {
String where = TABLE_NAME + "." + MmsSmsColumns.THREAD_ID + " = ? AND " +
TABLE_NAME + "." + getDateReceivedColumnName() + " < ?";
String[] args = SqlUtil.buildArgs(threadId, timestamp);
try (Reader reader = readerFor(rawQuery(where, args, true, limit))) {
List<MessageRecord> results = new ArrayList<>(reader.cursor.getCount());
while (reader.getNext() != null) {
results.add(reader.getCurrent());
}
return results;
}
}
@Override
public List<MessageRecord> getMessagesInThreadAfterInclusive(long threadId, long timestamp, long limit) {
String where = TABLE_NAME + "." + MmsSmsColumns.THREAD_ID + " = ? AND " +
TABLE_NAME + "." + getDateReceivedColumnName() + " >= ?";
String[] args = SqlUtil.buildArgs(threadId, timestamp);
try (Reader reader = readerFor(rawQuery(where, args, false, limit))) {
List<MessageRecord> results = new ArrayList<>(reader.cursor.getCount());
while (reader.getNext() != null) {
results.add(reader.getCurrent());
}
return results;
}
}
@Override
public void deleteAllThreads() {
DatabaseFactory.getAttachmentDatabase(context).deleteAllAttachments();

View File

@@ -22,6 +22,8 @@ import android.database.Cursor;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.annimon.stream.Stream;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteQueryBuilder;
@@ -33,7 +35,9 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.whispersystems.libsignal.util.Pair;
import java.io.Closeable;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class MmsSmsDatabase extends Database {
@@ -158,6 +162,30 @@ public class MmsSmsDatabase extends Database {
return null;
}
public @NonNull List<MessageRecord> getMessagesBeforeVoiceNoteExclusive(long messageId, long limit) throws NoSuchMessageException {
MessageRecord origin = DatabaseFactory.getMmsDatabase(context).getMessageRecord(messageId);
List<MessageRecord> mms = DatabaseFactory.getMmsDatabase(context).getMessagesInThreadBeforeExclusive(origin.getThreadId(), origin.getDateReceived(), limit);
List<MessageRecord> sms = DatabaseFactory.getSmsDatabase(context).getMessagesInThreadBeforeExclusive(origin.getThreadId(), origin.getDateReceived(), limit);
mms.addAll(sms);
Collections.sort(mms, (a, b) -> Long.compare(a.getDateReceived(), b.getDateReceived()));
return Stream.of(mms).skip(Math.max(0, mms.size() - limit)).toList();
}
public @NonNull List<MessageRecord> getMessagesAfterVoiceNoteInclusive(long messageId, long limit) throws NoSuchMessageException {
MessageRecord origin = DatabaseFactory.getMmsDatabase(context).getMessageRecord(messageId);
List<MessageRecord> mms = DatabaseFactory.getMmsDatabase(context).getMessagesInThreadAfterInclusive(origin.getThreadId(), origin.getDateReceived(), limit);
List<MessageRecord> sms = DatabaseFactory.getSmsDatabase(context).getMessagesInThreadAfterInclusive(origin.getThreadId(), origin.getDateReceived(), limit);
mms.addAll(sms);
Collections.sort(mms, (a, b) -> Long.compare(a.getDateReceived(), b.getDateReceived()));
return Stream.of(mms).limit(limit).toList();
}
public Cursor getConversation(long threadId, long offset, long limit) {
String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " DESC";
String selection = MmsSmsColumns.THREAD_ID + " = " + threadId;

View File

@@ -58,8 +58,10 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.util.Pair;
import org.whispersystems.libsignal.util.guava.Optional;
import java.io.Closeable;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
@@ -983,6 +985,53 @@ public class SmsDatabase extends MessageDatabase {
db.delete(TABLE_NAME, where, null);
}
@Override
public List<MessageRecord> getMessagesInThreadBeforeExclusive(long threadId, long timestamp, long limit) {
String where = TABLE_NAME + "." + MmsSmsColumns.THREAD_ID + " = ? AND " +
TABLE_NAME + "." + getDateReceivedColumnName() + " < ?";
String[] args = SqlUtil.buildArgs(threadId, timestamp);
try (Reader reader = readerFor(queryMessages(where, args, true, limit))) {
List<MessageRecord> results = new ArrayList<>(reader.cursor.getCount());
while (reader.getNext() != null) {
results.add(reader.getCurrent());
}
return results;
}
}
@Override
public List<MessageRecord> getMessagesInThreadAfterInclusive(long threadId, long timestamp, long limit) {
String where = TABLE_NAME + "." + MmsSmsColumns.THREAD_ID + " = ? AND " +
TABLE_NAME + "." + getDateReceivedColumnName() + " >= ?";
String[] args = SqlUtil.buildArgs(threadId, timestamp);
try (Reader reader = readerFor(queryMessages(where, args, false, limit))) {
List<MessageRecord> results = new ArrayList<>(reader.cursor.getCount());
while (reader.getNext() != null) {
results.add(reader.getCurrent());
}
return results;
}
}
private Cursor queryMessages(@NonNull String where, @NonNull String[] args, boolean reverse, long limit) {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
return db.query(TABLE_NAME,
MESSAGE_PROJECTION,
where,
args,
null,
null,
reverse ? ID + " DESC" : null,
limit > 0 ? String.valueOf(limit) : null);
}
@Override
void deleteThreads(@NonNull Set<Long> threadIds) {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
@@ -1185,7 +1234,7 @@ public class SmsDatabase extends MessageDatabase {
}
}
public static class Reader {
public static class Reader implements Closeable {
private final Cursor cursor;
private final Context context;
@@ -1256,6 +1305,7 @@ public class SmsDatabase extends MessageDatabase {
return new LinkedList<>();
}
@Override
public void close() {
cursor.close();
}