mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-22 09:49:30 +01:00
Add phased SMS removal UX.
This commit is contained in:
committed by
Greyson Parrelli
parent
8a238a66e7
commit
b6db7e7af6
@@ -13,6 +13,7 @@ import com.google.android.mms.pdu_alt.NotificationInd;
|
||||
import net.zetetic.database.sqlcipher.SQLiteStatement;
|
||||
|
||||
import org.signal.core.util.CursorUtil;
|
||||
import org.signal.core.util.SQLiteDatabaseExtensionsKt;
|
||||
import org.signal.core.util.SqlUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
@@ -97,7 +98,6 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
|
||||
public abstract List<MessageRecord> getProfileChangeDetailsRecords(long threadId, long afterTimestamp);
|
||||
public abstract Set<Long> getAllRateLimitedMessageIds();
|
||||
public abstract Cursor getUnexportedInsecureMessages(int limit);
|
||||
public abstract int getInsecureMessageCount();
|
||||
public abstract void deleteExportedMessages();
|
||||
|
||||
public abstract void markExpireStarted(long messageId);
|
||||
@@ -177,6 +177,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
|
||||
public abstract void insertNumberChangeMessages(@NonNull Recipient recipient);
|
||||
public abstract void insertBoostRequestMessage(@NonNull RecipientId recipientId, long threadId);
|
||||
public abstract void insertThreadMergeEvent(@NonNull RecipientId recipientId, long threadId, @NonNull ThreadMergeEvent event);
|
||||
public abstract void insertSmsExportMessage(@NonNull RecipientId recipientId, long threadId);
|
||||
|
||||
public abstract boolean deleteMessage(long messageId);
|
||||
abstract void deleteThread(long threadId);
|
||||
@@ -247,6 +248,20 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
|
||||
return getMessageCountForRecipientsAndType(getOutgoingInsecureMessageClause());
|
||||
}
|
||||
|
||||
public int getInsecureMessageCount() {
|
||||
try (Cursor cursor = getReadableDatabase().query(getTableName(), SqlUtil.COUNT, getInsecureMessageClause(), null, null, null, null)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
return cursor.getInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean hasSmsExportMessage(long threadId) {
|
||||
return SQLiteDatabaseExtensionsKt.exists(getReadableDatabase(), getTableName(), THREAD_ID_WHERE + " AND " + getTypeField() + " = ?", threadId, Types.SMS_EXPORT_TYPE);
|
||||
}
|
||||
|
||||
final int getSecureMessageCountForInsights() {
|
||||
return getMessageCountForRecipientsAndType(getOutgoingSecureMessageClause());
|
||||
}
|
||||
@@ -360,16 +375,30 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
|
||||
}
|
||||
|
||||
protected String getInsecureMessageClause() {
|
||||
return getInsecureMessageClause(-1);
|
||||
}
|
||||
|
||||
protected String getInsecureMessageClause(long threadId) {
|
||||
String isSent = "(" + getTypeField() + " & " + Types.BASE_TYPE_MASK + ") = " + Types.BASE_SENT_TYPE;
|
||||
String isReceived = "(" + getTypeField() + " & " + Types.BASE_TYPE_MASK + ") = " + Types.BASE_INBOX_TYPE;
|
||||
String isSecure = "(" + getTypeField() + " & " + (Types.SECURE_MESSAGE_BIT | Types.PUSH_MESSAGE_BIT) + ")";
|
||||
String isNotSecure = "(" + getTypeField() + " <= " + (Types.BASE_TYPE_MASK | Types.MESSAGE_ATTRIBUTE_MASK) + ")";
|
||||
|
||||
return String.format(Locale.ENGLISH, "(%s OR %s) AND NOT %s AND %s", isSent, isReceived, isSecure, isNotSecure);
|
||||
String whereClause = String.format(Locale.ENGLISH, "(%s OR %s) AND NOT %s AND %s", isSent, isReceived, isSecure, isNotSecure);
|
||||
|
||||
if (threadId != -1) {
|
||||
whereClause += " AND " + THREAD_ID + " = " + threadId;
|
||||
}
|
||||
|
||||
return whereClause;
|
||||
}
|
||||
|
||||
public int getUnexportedInsecureMessagesCount() {
|
||||
try (Cursor cursor = getWritableDatabase().query(getTableName(), SqlUtil.COUNT, getInsecureMessageClause() + " AND NOT " + EXPORTED, null, null, null, null)) {
|
||||
return getUnexportedInsecureMessagesCount(-1);
|
||||
}
|
||||
|
||||
public int getUnexportedInsecureMessagesCount(long threadId) {
|
||||
try (Cursor cursor = getWritableDatabase().query(getTableName(), SqlUtil.COUNT, getInsecureMessageClause(threadId) + " AND NOT " + EXPORTED, null, null, null, null)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
return cursor.getInt(0);
|
||||
}
|
||||
|
||||
@@ -578,6 +578,11 @@ public class MmsDatabase extends MessageDatabase {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertSmsExportMessage(@NonNull RecipientId recipientId, long threadId) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endTransaction(SQLiteDatabase database) {
|
||||
database.endTransaction();
|
||||
@@ -2456,17 +2461,6 @@ public class MmsDatabase extends MessageDatabase {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInsecureMessageCount() {
|
||||
try (Cursor cursor = getWritableDatabase().query(TABLE_NAME, SqlUtil.COUNT, getInsecureMessageClause(), null, null, null, null)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
return cursor.getInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteExportedMessages() {
|
||||
beginTransaction();
|
||||
|
||||
@@ -82,6 +82,7 @@ public interface MmsSmsColumns {
|
||||
protected static final long CHANGE_NUMBER_TYPE = 14;
|
||||
protected static final long BOOST_REQUEST_TYPE = 15;
|
||||
protected static final long THREAD_MERGE_TYPE = 16;
|
||||
protected static final long SMS_EXPORT_TYPE = 17;
|
||||
|
||||
protected static final long BASE_INBOX_TYPE = 20;
|
||||
protected static final long BASE_OUTBOX_TYPE = 21;
|
||||
@@ -366,6 +367,10 @@ public interface MmsSmsColumns {
|
||||
return type == BOOST_REQUEST_TYPE;
|
||||
}
|
||||
|
||||
public static boolean isSmsExport(long type) {
|
||||
return type == SMS_EXPORT_TYPE;
|
||||
}
|
||||
|
||||
public static boolean isGroupV2LeaveOnly(long type) {
|
||||
return (type & GROUP_V2_LEAVE_BITS) == GROUP_V2_LEAVE_BITS;
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ public class MmsSmsDatabase extends Database {
|
||||
MmsDatabase.PARENT_STORY_ID};
|
||||
|
||||
private static final String SNIPPET_QUERY = "SELECT " + MmsSmsColumns.ID + ", 0 AS " + TRANSPORT + ", " + SmsDatabase.TYPE + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + SmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + SmsDatabase.TABLE_NAME + " " +
|
||||
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + SmsDatabase.TYPE + " NOT IN (" + SmsDatabase.Types.PROFILE_CHANGE_TYPE + ", " + SmsDatabase.Types.GV1_MIGRATION_TYPE + ", " + SmsDatabase.Types.CHANGE_NUMBER_TYPE + ", " + SmsDatabase.Types.BOOST_REQUEST_TYPE + ") AND " + SmsDatabase.TYPE + " & " + GROUP_V2_LEAVE_BITS + " != " + GROUP_V2_LEAVE_BITS + " " +
|
||||
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + SmsDatabase.TYPE + " NOT IN (" + SmsDatabase.Types.PROFILE_CHANGE_TYPE + ", " + SmsDatabase.Types.GV1_MIGRATION_TYPE + ", " + SmsDatabase.Types.CHANGE_NUMBER_TYPE + ", " + SmsDatabase.Types.BOOST_REQUEST_TYPE + ", " + SmsDatabase.Types.SMS_EXPORT_TYPE + ") AND " + SmsDatabase.TYPE + " & " + GROUP_V2_LEAVE_BITS + " != " + GROUP_V2_LEAVE_BITS + " " +
|
||||
"UNION ALL " +
|
||||
"SELECT " + MmsSmsColumns.ID + ", 1 AS " + TRANSPORT + ", " + MmsDatabase.MESSAGE_BOX + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + MmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + MmsDatabase.TABLE_NAME + " " +
|
||||
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + MmsDatabase.MESSAGE_BOX + " & " + GROUP_V2_LEAVE_BITS + " != " + GROUP_V2_LEAVE_BITS + " AND " + MmsDatabase.STORY_TYPE + " = 0 AND " + MmsDatabase.PARENT_STORY_ID + " <= 0 " +
|
||||
@@ -401,6 +401,17 @@ public class MmsSmsDatabase extends Database {
|
||||
return count;
|
||||
}
|
||||
|
||||
public int getUnexportedInsecureMessagesCount() {
|
||||
return getUnexportedInsecureMessagesCount(-1);
|
||||
}
|
||||
|
||||
public int getUnexportedInsecureMessagesCount(long threadId) {
|
||||
int count = SignalDatabase.sms().getUnexportedInsecureMessagesCount(threadId);
|
||||
count += SignalDatabase.mms().getUnexportedInsecureMessagesCount(threadId);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public int getIncomingMeaningfulMessageCountSince(long threadId, long afterTime) {
|
||||
int count = SignalDatabase.sms().getIncomingMeaningfulMessageCountSince(threadId, afterTime);
|
||||
count += SignalDatabase.mms().getIncomingMeaningfulMessageCountSince(threadId, afterTime);
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import net.zetetic.database.sqlcipher.SQLiteStatement;
|
||||
|
||||
import org.signal.core.util.CursorUtil;
|
||||
import org.signal.core.util.SQLiteDatabaseExtensionsKt;
|
||||
import org.signal.core.util.SqlUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.libsignal.protocol.util.Pair;
|
||||
@@ -300,8 +301,8 @@ public class SmsDatabase extends MessageDatabase {
|
||||
}
|
||||
|
||||
private @NonNull SqlUtil.Query buildMeaningfulMessagesQuery(long threadId) {
|
||||
String query = THREAD_ID + " = ? AND (NOT " + TYPE + " & ? AND " + TYPE + " != ? AND " + TYPE + " != ? AND " + TYPE + " != ? AND " + TYPE + " & " + GROUP_V2_LEAVE_BITS + " != " + GROUP_V2_LEAVE_BITS + ")";
|
||||
return SqlUtil.buildQuery(query, threadId, IGNORABLE_TYPESMASK_WHEN_COUNTING, Types.PROFILE_CHANGE_TYPE, Types.CHANGE_NUMBER_TYPE, Types.BOOST_REQUEST_TYPE);
|
||||
String query = THREAD_ID + " = ? AND (NOT " + TYPE + " & ? AND " + TYPE + " != ? AND " + TYPE + " != ? AND " + TYPE + " != ? AND " + TYPE + " != ? AND " + TYPE + " & " + GROUP_V2_LEAVE_BITS + " != " + GROUP_V2_LEAVE_BITS + ")";
|
||||
return SqlUtil.buildQuery(query, threadId, IGNORABLE_TYPESMASK_WHEN_COUNTING, Types.PROFILE_CHANGE_TYPE, Types.CHANGE_NUMBER_TYPE, Types.SMS_EXPORT_TYPE, Types.BOOST_REQUEST_TYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -918,17 +919,6 @@ public class SmsDatabase extends MessageDatabase {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInsecureMessageCount() {
|
||||
try (Cursor cursor = getWritableDatabase().query(TABLE_NAME, SqlUtil.COUNT, getInsecureMessageClause(), null, null, null, null)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
return cursor.getInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteExportedMessages() {
|
||||
beginTransaction();
|
||||
@@ -1139,6 +1129,32 @@ public class SmsDatabase extends MessageDatabase {
|
||||
ApplicationDependencies.getDatabaseObserver().notifyConversationListeners(threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertSmsExportMessage(@NonNull RecipientId recipientId, long threadId) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(RECIPIENT_ID, recipientId.serialize());
|
||||
values.put(ADDRESS_DEVICE_ID, 1);
|
||||
values.put(DATE_RECEIVED, System.currentTimeMillis());
|
||||
values.put(DATE_SENT, System.currentTimeMillis());
|
||||
values.put(READ, 1);
|
||||
values.put(TYPE, Types.SMS_EXPORT_TYPE);
|
||||
values.put(THREAD_ID, threadId);
|
||||
values.putNull(BODY);
|
||||
|
||||
boolean updated = SQLiteDatabaseExtensionsKt.withinTransaction(getWritableDatabase(), db -> {
|
||||
if (SignalDatabase.sms().hasSmsExportMessage(threadId)) {
|
||||
return false;
|
||||
} else {
|
||||
db.insert(TABLE_NAME, null, values);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (updated) {
|
||||
ApplicationDependencies.getDatabaseObserver().notifyConversationListeners(threadId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<InsertResult> insertMessageInbox(IncomingTextMessage message, long type) {
|
||||
boolean tryToCollapseJoinRequestEvents = false;
|
||||
|
||||
@@ -236,6 +236,10 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
} else if (isSmsExportType()) {
|
||||
int messageResource = SignalStore.misc().getSmsExportPhase().isSmsSupported() ? R.string.MessageRecord__you_will_on_longer_be_able_to_send_sms_messages_from_signal_soon
|
||||
: R.string.MessageRecord__you_can_no_longer_send_sms_messages_in_signal;
|
||||
return fromRecipient(getIndividualRecipient(), r -> context.getString(messageResource, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -542,6 +546,10 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
return MmsSmsColumns.Types.isThreadMergeType(type);
|
||||
}
|
||||
|
||||
public boolean isSmsExportType() {
|
||||
return MmsSmsColumns.Types.isSmsExport(type);
|
||||
}
|
||||
|
||||
public boolean isInvalidVersionKeyExchange() {
|
||||
return SmsDatabase.Types.isInvalidVersionKeyExchange(type);
|
||||
}
|
||||
@@ -562,7 +570,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() ||
|
||||
isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() ||
|
||||
isProfileChange() || isGroupV1MigrationEvent() || isChatSessionRefresh() || isBadDecryptType() ||
|
||||
isChangeNumber() || isBoostRequest() || isThreadMergeEventType();
|
||||
isChangeNumber() || isBoostRequest() || isThreadMergeEventType() || isSmsExportType();
|
||||
}
|
||||
|
||||
public boolean isMediaPending() {
|
||||
|
||||
Reference in New Issue
Block a user