Add universal disappearing messages.

This commit is contained in:
Cody Henthorne
2021-05-18 15:19:33 -04:00
committed by Greyson Parrelli
parent 8c6a88374b
commit defd5e8047
70 changed files with 1513 additions and 251 deletions

View File

@@ -77,6 +77,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
public abstract int getMessageCountForThread(long threadId);
public abstract int getMessageCountForThread(long threadId, long beforeTime);
abstract int getMessageCountForThreadSummary(long threadId);
public abstract boolean hasMeaningfulMessage(long threadId);
public abstract Optional<MmsNotificationInfo> getNotification(long messageId);
public abstract Cursor getExpirationStartedMessages();

View File

@@ -620,6 +620,19 @@ public class MmsDatabase extends MessageDatabase {
return 0;
}
@Override
public boolean hasMeaningfulMessage(long threadId) {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
String[] cols = new String[] { "1" };
String query = THREAD_ID + " = ?";
String[] args = SqlUtil.buildArgs(threadId);
try (Cursor cursor = db.query(TABLE_NAME, cols, query, args, null, null, null, "1")) {
return cursor != null && cursor.moveToFirst();
}
}
@Override
public void addFailures(long messageId, List<NetworkFailure> failure) {
try {

View File

@@ -337,6 +337,15 @@ public class MmsSmsDatabase extends Database {
return count;
}
public boolean hasMeaningfulMessage(long threadId) {
if (threadId == -1) {
return false;
}
return DatabaseFactory.getSmsDatabase(context).hasMeaningfulMessage(threadId) ||
DatabaseFactory.getMmsDatabase(context).hasMeaningfulMessage(threadId);
}
public long getThreadForMessageId(long messageId) {
long id = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageId);

View File

@@ -233,14 +233,11 @@ public class SmsDatabase extends MessageDatabase {
@Override
public int getMessageCountForThreadSummary(long threadId) {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
SQLiteDatabase db = databaseHelper.getReadableDatabase();
SqlUtil.Query query = buildMeaningfulMessagesQuery(threadId);
String[] cols = { "COUNT(*)" };
String[] cols = { "COUNT(*)" };
String query = THREAD_ID + " = ? AND (NOT " + TYPE + " & ? AND TYPE != ?)";
long type = Types.END_SESSION_BIT | Types.KEY_EXCHANGE_IDENTITY_UPDATE_BIT | Types.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT;
String[] args = SqlUtil.buildArgs(threadId, type, Types.PROFILE_CHANGE_TYPE);
try (Cursor cursor = db.query(TABLE_NAME, cols, query, args, null, null, null)) {
try (Cursor cursor = db.query(TABLE_NAME, cols, query.getWhere(), query.getWhereArgs(), null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
int count = cursor.getInt(0);
if (count > 0) {
@@ -286,6 +283,22 @@ public class SmsDatabase extends MessageDatabase {
return 0;
}
@Override
public boolean hasMeaningfulMessage(long threadId) {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
SqlUtil.Query query = buildMeaningfulMessagesQuery(threadId);
try (Cursor cursor = db.query(TABLE_NAME, new String[] { "1" }, query.getWhere(), query.getWhereArgs(), null, null, null, "1")) {
return cursor != null && cursor.moveToFirst();
}
}
private @NonNull SqlUtil.Query buildMeaningfulMessagesQuery(long threadId) {
String query = THREAD_ID + " = ? AND (NOT " + TYPE + " & ? AND TYPE != ?)";
long type = Types.END_SESSION_BIT | Types.KEY_EXCHANGE_IDENTITY_UPDATE_BIT | Types.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT;
return SqlUtil.buildQuery(query, threadId, type, Types.PROFILE_CHANGE_TYPE);
}
@Override
public void markAsEndSession(long id) {
updateTypeBitmask(id, Types.KEY_EXCHANGE_MASK, Types.END_SESSION_BIT);

View File

@@ -176,8 +176,12 @@ public class ThreadDatabase extends Database {
contentValues.put(MESSAGE_COUNT, 0);
SQLiteDatabase db = databaseHelper.getWritableDatabase();
return db.insert(TABLE_NAME, null, contentValues);
SQLiteDatabase db = databaseHelper.getWritableDatabase();
long result = db.insert(TABLE_NAME, null, contentValues);
Recipient.live(recipientId).refresh();
return result;
}
private void updateThread(long threadId, long count, String body, @Nullable Uri attachment,

View File

@@ -475,7 +475,7 @@ final class GroupsV2UpdateMessageProducer {
}
}
private void describeNewTimer(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
void describeNewTimer(@NonNull DecryptedGroupChange change, @NonNull List<UpdateDescription> updates) {
boolean editorIsYou = change.getEditor().equals(selfUuidBytes);
if (change.hasNewTimer()) {

View File

@@ -7,7 +7,9 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.ExpirationUtil;
import java.util.Collections;
@@ -16,6 +18,9 @@ import java.util.Collections;
*/
public class InMemoryMessageRecord extends MessageRecord {
private static final int NO_GROUPS_IN_COMMON_ID = -1;
private static final int UNIVERSAL_EXPIRE_TIMER_ID = -2;
private InMemoryMessageRecord(long id,
String body,
Recipient conversationRecipient,
@@ -78,7 +83,7 @@ public class InMemoryMessageRecord extends MessageRecord {
private final boolean isGroup;
public NoGroupsInCommon(long threadId, boolean isGroup) {
super(-1, "", Recipient.UNKNOWN, threadId, 0);
super(NO_GROUPS_IN_COMMON_ID, "", Recipient.UNKNOWN, threadId, 0);
this.isGroup = isGroup;
}
@@ -108,4 +113,28 @@ public class InMemoryMessageRecord extends MessageRecord {
return R.string.ConversationUpdateItem_learn_more;
}
}
/**
* Show temporary update message about setting the disappearing messages timer upon first message
* send.
*/
public static final class UniversalExpireTimerUpdate extends InMemoryMessageRecord {
public UniversalExpireTimerUpdate(long threadId) {
super(UNIVERSAL_EXPIRE_TIMER_ID, "", Recipient.UNKNOWN, threadId, 0);
}
@Override
public @Nullable UpdateDescription getUpdateDisplayBody(@NonNull Context context) {
String update = context.getString(R.string.ConversationUpdateItem_the_disappearing_message_time_will_be_set_to_s_when_you_message_them,
ExpirationUtil.getExpirationDisplayValue(context, SignalStore.settings().getUniversalExpireTimer()));
return UpdateDescription.staticDescription(update, R.drawable.ic_update_timer_16);
}
@Override
public boolean isUpdate() {
return true;
}
}
}

View File

@@ -240,11 +240,18 @@ public abstract class MessageRecord extends DisplayRecord {
if (decryptedGroupV2Context.hasChange() && (decryptedGroupV2Context.getGroupState().getRevision() != 0 || decryptedGroupV2Context.hasPreviousGroupState())) {
return UpdateDescription.concatWithNewLines(updateMessageProducer.describeChanges(decryptedGroupV2Context.getPreviousGroupState(), decryptedGroupV2Context.getChange()));
} else if (selfCreatedGroup(decryptedGroupV2Context.getChange())) {
return UpdateDescription.concatWithNewLines(Arrays.asList(updateMessageProducer.describeNewGroup(decryptedGroupV2Context.getGroupState(), decryptedGroupV2Context.getChange()),
staticUpdateDescription(context.getString(R.string.MessageRecord_invite_friends_to_this_group), 0)));
} else {
return updateMessageProducer.describeNewGroup(decryptedGroupV2Context.getGroupState(), decryptedGroupV2Context.getChange());
List<UpdateDescription> newGroupDescriptions = new ArrayList<>();
newGroupDescriptions.add(updateMessageProducer.describeNewGroup(decryptedGroupV2Context.getGroupState(), decryptedGroupV2Context.getChange()));
if (decryptedGroupV2Context.getChange().hasNewTimer()) {
updateMessageProducer.describeNewTimer(decryptedGroupV2Context.getChange(), newGroupDescriptions);
}
if (selfCreatedGroup(decryptedGroupV2Context.getChange())) {
newGroupDescriptions.add(staticUpdateDescription(context.getString(R.string.MessageRecord_invite_friends_to_this_group), 0));
}
return UpdateDescription.concatWithNewLines(newGroupDescriptions);
}
} catch (IOException e) {
Log.w(TAG, "GV2 Message update detail could not be read", e);