mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-22 01:40:07 +01:00
Add in-chat payment activation requests.
Co-authored-by: Varsha <varsha@mobilecoin.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import com.google.android.mms.pdu_alt.NotificationInd;
|
||||
|
||||
import net.zetetic.database.sqlcipher.SQLiteStatement;
|
||||
|
||||
import org.signal.core.util.CursorExtensionsKt;
|
||||
import org.signal.core.util.CursorUtil;
|
||||
import org.signal.core.util.SQLiteDatabaseExtensionsKt;
|
||||
import org.signal.core.util.SqlUtil;
|
||||
@@ -517,6 +518,15 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
|
||||
return data;
|
||||
}
|
||||
|
||||
public List<Long> getIncomingPaymentRequestThreads() {
|
||||
Cursor cursor = SQLiteDatabaseExtensionsKt.select(getReadableDatabase(), "DISTINCT " + THREAD_ID)
|
||||
.from(getTableName())
|
||||
.where("(" + getTypeField() + " & " + Types.BASE_TYPE_MASK + ") = " + Types.BASE_INBOX_TYPE + " AND (" + getTypeField() + " & ?) != 0", Types.SPECIAL_TYPE_ACTIVATE_PAYMENTS_REQUEST)
|
||||
.run();
|
||||
|
||||
return CursorExtensionsKt.readToList(cursor, c -> CursorUtil.requireLong(c, THREAD_ID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remapRecipient(@NonNull RecipientId fromId, @NonNull RecipientId toId) {
|
||||
ContentValues values = new ContentValues();
|
||||
|
||||
@@ -78,6 +78,8 @@ import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingGroupUpdateMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingPaymentsActivatedMessages;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingRequestToActivatePaymentMessages;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.QuoteModel;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
@@ -1794,6 +1796,10 @@ public class MmsDatabase extends MessageDatabase {
|
||||
return new OutgoingGroupUpdateMessage(recipient, new MessageGroupContext(body, Types.isGroupV2(outboxType)), attachments, timestamp, 0, false, quote, contacts, previews, mentions);
|
||||
} else if (Types.isExpirationTimerUpdate(outboxType)) {
|
||||
return new OutgoingExpirationUpdateMessage(recipient, timestamp, expiresIn);
|
||||
} else if (Types.isRequestToActivatePayments(outboxType)) {
|
||||
return new OutgoingRequestToActivatePaymentMessages(recipient, timestamp, expiresIn);
|
||||
} else if (Types.isPaymentsActivated(outboxType)) {
|
||||
return new OutgoingPaymentsActivatedMessages(recipient, timestamp, expiresIn);
|
||||
}
|
||||
|
||||
GiftBadge giftBadge = null;
|
||||
@@ -1987,7 +1993,7 @@ public class MmsDatabase extends MessageDatabase {
|
||||
updateThread);
|
||||
|
||||
boolean isNotStoryGroupReply = retrieved.getParentStoryId() == null || !retrieved.getParentStoryId().isGroupReply();
|
||||
if (!Types.isExpirationTimerUpdate(mailbox) && !retrieved.getStoryType().isStory() && isNotStoryGroupReply) {
|
||||
if (!Types.isPaymentsActivated(mailbox) && !Types.isRequestToActivatePayments(mailbox) && !Types.isExpirationTimerUpdate(mailbox) && !retrieved.getStoryType().isStory() && isNotStoryGroupReply) {
|
||||
boolean incrementUnreadMentions = !retrieved.getMentions().isEmpty() && retrieved.getMentions().stream().anyMatch(m -> m.getRecipientId().equals(Recipient.self().getId()));
|
||||
SignalDatabase.threads().incrementUnread(threadId, 1, incrementUnreadMentions ? 1 : 0);
|
||||
SignalDatabase.threads().update(threadId, true);
|
||||
@@ -2013,6 +2019,14 @@ public class MmsDatabase extends MessageDatabase {
|
||||
type |= Types.EXPIRATION_TIMER_UPDATE_BIT;
|
||||
}
|
||||
|
||||
if (retrieved.isActivatePaymentsRequest()) {
|
||||
type |= Types.SPECIAL_TYPE_ACTIVATE_PAYMENTS_REQUEST;
|
||||
}
|
||||
|
||||
if (retrieved.isPaymentsActivated()) {
|
||||
type |= Types.SPECIAL_TYPE_PAYMENTS_ACTIVATED;
|
||||
}
|
||||
|
||||
return insertMessageInbox(retrieved, contentLocation, threadId, type);
|
||||
}
|
||||
|
||||
@@ -2044,6 +2058,20 @@ public class MmsDatabase extends MessageDatabase {
|
||||
type |= Types.SPECIAL_TYPE_GIFT_BADGE;
|
||||
}
|
||||
|
||||
if (retrieved.isActivatePaymentsRequest()) {
|
||||
if (hasSpecialType) {
|
||||
throw new MmsException("Cannot insert message with multiple special types.");
|
||||
}
|
||||
type |= Types.SPECIAL_TYPE_ACTIVATE_PAYMENTS_REQUEST;
|
||||
}
|
||||
|
||||
if (retrieved.isPaymentsActivated()) {
|
||||
if (hasSpecialType) {
|
||||
throw new MmsException("Cannot insert message with multiple special types.");
|
||||
}
|
||||
type |= Types.SPECIAL_TYPE_PAYMENTS_ACTIVATED;
|
||||
}
|
||||
|
||||
return insertMessageInbox(retrieved, "", threadId, type);
|
||||
}
|
||||
|
||||
@@ -2211,6 +2239,20 @@ public class MmsDatabase extends MessageDatabase {
|
||||
type |= Types.SPECIAL_TYPE_GIFT_BADGE;
|
||||
}
|
||||
|
||||
if (message.isRequestToActivatePayments()) {
|
||||
if (hasSpecialType) {
|
||||
throw new MmsException("Cannot insert message with multiple special types.");
|
||||
}
|
||||
type |= Types.SPECIAL_TYPE_ACTIVATE_PAYMENTS_REQUEST;
|
||||
}
|
||||
|
||||
if (message.isPaymentsActivated()) {
|
||||
if (hasSpecialType) {
|
||||
throw new MmsException("Cannot insert message with multiple special types.");
|
||||
}
|
||||
type |= Types.SPECIAL_TYPE_PAYMENTS_ACTIVATED;
|
||||
}
|
||||
|
||||
Map<RecipientId, EarlyReceiptCache.Receipt> earlyDeliveryReceipts = earlyDeliveryReceiptCache.remove(message.getSentTimeMillis());
|
||||
|
||||
ContentValues contentValues = new ContentValues();
|
||||
|
||||
@@ -140,9 +140,11 @@ public interface MmsSmsColumns {
|
||||
protected static final long ENCRYPTION_REMOTE_LEGACY_BIT = 0x02000000;
|
||||
|
||||
// Special message types
|
||||
public static final long SPECIAL_TYPES_MASK = 0xF00000000L;
|
||||
public static final long SPECIAL_TYPE_STORY_REACTION = 0x100000000L;
|
||||
public static final long SPECIAL_TYPE_GIFT_BADGE = 0x200000000L;
|
||||
public static final long SPECIAL_TYPES_MASK = 0xF00000000L;
|
||||
public static final long SPECIAL_TYPE_STORY_REACTION = 0x100000000L;
|
||||
public static final long SPECIAL_TYPE_GIFT_BADGE = 0x200000000L;
|
||||
protected static final long SPECIAL_TYPE_ACTIVATE_PAYMENTS_REQUEST = 0x400000000L;
|
||||
protected static final long SPECIAL_TYPE_PAYMENTS_ACTIVATED = 0x800000000L;
|
||||
|
||||
public static boolean isStoryReaction(long type) {
|
||||
return (type & SPECIAL_TYPES_MASK) == SPECIAL_TYPE_STORY_REACTION;
|
||||
@@ -152,6 +154,14 @@ public interface MmsSmsColumns {
|
||||
return (type & SPECIAL_TYPES_MASK) == SPECIAL_TYPE_GIFT_BADGE;
|
||||
}
|
||||
|
||||
public static boolean isRequestToActivatePayments(long type) {
|
||||
return (type & SPECIAL_TYPES_MASK) == SPECIAL_TYPE_ACTIVATE_PAYMENTS_REQUEST;
|
||||
}
|
||||
|
||||
public static boolean isPaymentsActivated(long type) {
|
||||
return (type & SPECIAL_TYPES_MASK) == SPECIAL_TYPE_PAYMENTS_ACTIVATED;
|
||||
}
|
||||
|
||||
public static boolean isDraftMessageType(long type) {
|
||||
return (type & BASE_TYPE_MASK) == BASE_DRAFT_TYPE;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ 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;
|
||||
import org.thoughtcrime.securesms.components.settings.app.chats.sms.SmsExportState;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchSet;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
|
||||
@@ -52,6 +52,10 @@ public final class ThreadBodyUtil {
|
||||
return String.format("%s %s", EmojiStrings.GIFT, getGiftSummary(context, record));
|
||||
} else if (MessageRecordUtil.isStoryReaction(record)) {
|
||||
return getStoryReactionSummary(context, record);
|
||||
} else if (MessageRecordUtil.isPaymentActivationRequest(record)) {
|
||||
return String.format("%s %s", EmojiStrings.CARD, getPaymentActivationRequestSummary(context, record));
|
||||
} else if (MessageRecordUtil.isPaymentsActivated(record)) {
|
||||
return String.format("%s %s", EmojiStrings.CARD, getPaymentActivatedSummary(context, record));
|
||||
}
|
||||
|
||||
boolean hasImage = false;
|
||||
@@ -94,6 +98,22 @@ public final class ThreadBodyUtil {
|
||||
return context.getString(R.string.ThreadRecord__reacted_s_to_your_story, messageRecord.getDisplayBody(context));
|
||||
}
|
||||
}
|
||||
|
||||
private static @NonNull String getPaymentActivationRequestSummary(@NonNull Context context, @NonNull MessageRecord messageRecord) {
|
||||
if (messageRecord.isOutgoing()) {
|
||||
return context.getString(R.string.ThreadRecord_you_sent_request);
|
||||
} else {
|
||||
return context.getString(R.string.ThreadRecord_wants_you_to_activate_payments, messageRecord.getRecipient().getShortDisplayName(context));
|
||||
}
|
||||
}
|
||||
|
||||
private static @NonNull String getPaymentActivatedSummary(@NonNull Context context, @NonNull MessageRecord messageRecord) {
|
||||
if (messageRecord.isOutgoing()) {
|
||||
return context.getString(R.string.ThreadRecord_you_activated_payments);
|
||||
} else {
|
||||
return context.getString(R.string.ThreadRecord_can_accept_payments, messageRecord.getRecipient().getShortDisplayName(context));
|
||||
}
|
||||
}
|
||||
|
||||
private static @NonNull String format(@NonNull Context context, @NonNull MessageRecord record, @NonNull String emoji, @StringRes int defaultStringRes) {
|
||||
return String.format("%s %s", emoji, getBodyOrDefault(context, record, defaultStringRes));
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.text.SpannableString;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
@@ -231,4 +232,12 @@ public abstract class DisplayRecord {
|
||||
public boolean isPendingInsecureSmsFallback() {
|
||||
return SmsDatabase.Types.isPendingInsecureSmsFallbackType(type);
|
||||
}
|
||||
|
||||
public boolean isRequestToActivatePayments() {
|
||||
return SmsDatabase.Types.isRequestToActivatePayments(type);
|
||||
}
|
||||
|
||||
public boolean isPaymentsActivated() {
|
||||
return SmsDatabase.Types.isPaymentsActivated(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +240,12 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
int messageResource = SignalStore.misc().getSmsExportPhase().isSmsSupported() ? R.string.MessageRecord__you_will_no_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);
|
||||
} else if (isRequestToActivatePayments()) {
|
||||
return isOutgoing() ? fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_sent_request, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments)
|
||||
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_wants_you_to_activate_payments, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments);
|
||||
} else if (isPaymentsActivated()) {
|
||||
return isOutgoing() ? staticUpdateDescription(context.getString(R.string.MessageRecord_you_activated_payments), R.drawable.ic_card_activate_payments)
|
||||
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_can_accept_payments, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -570,7 +576,8 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() ||
|
||||
isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() ||
|
||||
isProfileChange() || isGroupV1MigrationEvent() || isChatSessionRefresh() || isBadDecryptType() ||
|
||||
isChangeNumber() || isBoostRequest() || isThreadMergeEventType() || isSmsExportType();
|
||||
isChangeNumber() || isBoostRequest() || isThreadMergeEventType() || isSmsExportType() ||
|
||||
isRequestToActivatePayments() || isPaymentsActivated();
|
||||
}
|
||||
|
||||
public boolean isMediaPending() {
|
||||
|
||||
Reference in New Issue
Block a user