Add in-chat payment messages.

This commit is contained in:
Cody Henthorne
2022-11-10 14:45:45 -05:00
committed by Greyson Parrelli
parent 28193c2f61
commit 1dc29fda12
43 changed files with 708 additions and 98 deletions

View File

@@ -522,7 +522,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns,
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)
.where("(" + getTypeField() + " & " + Types.BASE_TYPE_MASK + ") = " + Types.BASE_INBOX_TYPE + " AND (" + getTypeField() + " & ?) != 0", Types.SPECIAL_TYPE_PAYMENTS_ACTIVATE_REQUEST)
.run();
return CursorExtensionsKt.readToList(cursor, c -> CursorUtil.requireLong(c, THREAD_ID));

View File

@@ -79,6 +79,7 @@ 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.OutgoingPaymentsNotificationMessage;
import org.thoughtcrime.securesms.mms.OutgoingRequestToActivatePaymentMessages;
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
import org.thoughtcrime.securesms.mms.QuoteModel;
@@ -109,6 +110,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@@ -1796,7 +1798,9 @@ 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)) {
} else if (Types.isPaymentsNotification(outboxType)) {
return new OutgoingPaymentsNotificationMessage(recipient, Objects.requireNonNull(body), timestamp, expiresIn);
} else if (Types.isPaymentsRequestToActivate(outboxType)) {
return new OutgoingRequestToActivatePaymentMessages(recipient, timestamp, expiresIn);
} else if (Types.isPaymentsActivated(outboxType)) {
return new OutgoingPaymentsActivatedMessages(recipient, timestamp, expiresIn);
@@ -1995,7 +1999,7 @@ public class MmsDatabase extends MessageDatabase {
!keepThreadArchived);
boolean isNotStoryGroupReply = retrieved.getParentStoryId() == null || !retrieved.getParentStoryId().isGroupReply();
if (!Types.isPaymentsActivated(mailbox) && !Types.isRequestToActivatePayments(mailbox) && !Types.isExpirationTimerUpdate(mailbox) && !retrieved.getStoryType().isStory() && isNotStoryGroupReply) {
if (!Types.isPaymentsActivated(mailbox) && !Types.isPaymentsRequestToActivate(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, !keepThreadArchived);
@@ -2021,8 +2025,12 @@ public class MmsDatabase extends MessageDatabase {
type |= Types.EXPIRATION_TIMER_UPDATE_BIT;
}
if (retrieved.isPaymentsNotification()) {
type |= Types.SPECIAL_TYPE_PAYMENTS_NOTIFICATION;
}
if (retrieved.isActivatePaymentsRequest()) {
type |= Types.SPECIAL_TYPE_ACTIVATE_PAYMENTS_REQUEST;
type |= Types.SPECIAL_TYPE_PAYMENTS_ACTIVATE_REQUEST;
}
if (retrieved.isPaymentsActivated()) {
@@ -2060,11 +2068,18 @@ public class MmsDatabase extends MessageDatabase {
type |= Types.SPECIAL_TYPE_GIFT_BADGE;
}
if (retrieved.isPaymentsNotification()) {
if (hasSpecialType) {
throw new MmsException("Cannot insert message with multiple special types.");
}
type |= Types.SPECIAL_TYPE_PAYMENTS_NOTIFICATION;
}
if (retrieved.isActivatePaymentsRequest()) {
if (hasSpecialType) {
throw new MmsException("Cannot insert message with multiple special types.");
}
type |= Types.SPECIAL_TYPE_ACTIVATE_PAYMENTS_REQUEST;
type |= Types.SPECIAL_TYPE_PAYMENTS_ACTIVATE_REQUEST;
}
if (retrieved.isPaymentsActivated()) {
@@ -2241,11 +2256,18 @@ public class MmsDatabase extends MessageDatabase {
type |= Types.SPECIAL_TYPE_GIFT_BADGE;
}
if (message.isPaymentsNotification()) {
if (hasSpecialType) {
throw new MmsException("Cannot insert message with multiple special types.");
}
type |= Types.SPECIAL_TYPE_PAYMENTS_NOTIFICATION;
}
if (message.isRequestToActivatePayments()) {
if (hasSpecialType) {
throw new MmsException("Cannot insert message with multiple special types.");
}
type |= Types.SPECIAL_TYPE_ACTIVATE_PAYMENTS_REQUEST;
type |= Types.SPECIAL_TYPE_PAYMENTS_ACTIVATE_REQUEST;
}
if (message.isPaymentsActivated()) {
@@ -2858,7 +2880,8 @@ public class MmsDatabase extends MessageDatabase {
null,
message.getStoryType(),
message.getParentStoryId(),
message.getGiftBadge());
message.getGiftBadge(),
null);
}
}
@@ -3047,7 +3070,7 @@ public class MmsDatabase extends MessageDatabase {
networkFailures, subscriptionId, expiresIn, expireStarted,
isViewOnce, readReceiptCount, quote, contacts, previews, unidentified, Collections.emptyList(),
remoteDelete, mentionsSelf, notifiedTimestamp, viewedReceiptCount, receiptTimestamp, messageRanges,
storyType, parentStoryId, giftBadge);
storyType, parentStoryId, giftBadge, null);
}
private Set<IdentityKeyMismatch> getMismatchedIdentities(String document) {

View File

@@ -47,7 +47,7 @@ public interface MmsSmsColumns {
* {@link #TOTAL_MASK}.
*
* <pre>
* ____________________________________________ SPECIAL TYPES (Story reactions) ({@link #SPECIAL_TYPES_MASK}
* ____________________________________________ SPECIAL TYPES ({@link #SPECIAL_TYPES_MASK}
* | _____________________________________ ENCRYPTION ({@link #ENCRYPTION_MASK})
* | | _____________________________ SECURE MESSAGE INFORMATION (no mask, but look at {@link #SECURE_MESSAGE_BIT})
* | | | ________________________ GROUPS (no mask, but look at {@link #GROUP_UPDATE_BIT})
@@ -143,7 +143,8 @@ public interface MmsSmsColumns {
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_NOTIFICATION = 0x300000000L;
protected static final long SPECIAL_TYPE_PAYMENTS_ACTIVATE_REQUEST = 0x400000000L;
protected static final long SPECIAL_TYPE_PAYMENTS_ACTIVATED = 0x800000000L;
public static boolean isStoryReaction(long type) {
@@ -154,8 +155,12 @@ 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 isPaymentsNotification(long type) {
return (type & SPECIAL_TYPES_MASK) == SPECIAL_TYPE_PAYMENTS_NOTIFICATION;
}
public static boolean isPaymentsRequestToActivate(long type) {
return (type & SPECIAL_TYPES_MASK) == SPECIAL_TYPE_PAYMENTS_ACTIVATE_REQUEST;
}
public static boolean isPaymentsActivated(long type) {

View File

@@ -14,7 +14,11 @@ import androidx.lifecycle.MutableLiveData;
import com.google.protobuf.InvalidProtocolBufferException;
import com.mobilecoin.lib.exceptions.SerializationException;
import org.signal.core.util.CursorExtensionsKt;
import org.signal.core.util.SQLiteDatabaseExtensionsKt;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.databaseprotos.CryptoValue;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.payments.CryptoValueUtil;
@@ -31,8 +35,11 @@ import org.signal.core.util.CursorUtil;
import org.signal.core.util.SqlUtil;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
import org.whispersystems.signalservice.api.payments.Money;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
@@ -104,10 +111,11 @@ public final class PaymentDatabase extends Database implements RecipientIdDataba
@NonNull String note,
@NonNull Money amount,
@NonNull Money fee,
@NonNull byte[] receipt)
@NonNull byte[] receipt,
boolean seen)
throws PublicKeyConflictException, SerializationException
{
create(uuid, fromRecipient, null, timestamp, 0, note, Direction.RECEIVED, State.SUBMITTED, amount, fee, null, receipt, null, false);
create(uuid, fromRecipient, null, timestamp, 0, note, Direction.RECEIVED, State.SUBMITTED, amount, fee, null, receipt, null, seen);
}
@WorkerThread
@@ -388,11 +396,44 @@ public final class PaymentDatabase extends Database implements RecipientIdDataba
}
}
public @NonNull List<Payment> getPayments(@Nullable Collection<UUID> paymentUuids) {
if (paymentUuids == null || paymentUuids.isEmpty()) {
return Collections.emptyList();
}
List<SqlUtil.Query> queries = SqlUtil.buildCollectionQuery(PAYMENT_UUID, paymentUuids);
List<Payment> payments = new LinkedList<>();
for (SqlUtil.Query query : queries) {
Cursor cursor = SQLiteDatabaseExtensionsKt.select(getReadableDatabase())
.from(TABLE_NAME)
.where(query.getWhere(), (Object[]) query.getWhereArgs())
.run();
payments.addAll(CursorExtensionsKt.readToList(cursor, PaymentDatabase::readPayment));
}
return payments;
}
@AnyThread
public @NonNull LiveData<List<PaymentTransaction>> getAllLive() {
return LiveDataUtil.mapAsync(changeSignal, change -> getAll());
}
@WorkerThread
public @NonNull MessageRecord updateMessageWithPayment(@NonNull MessageRecord record) {
if (record.isPaymentNotification()) {
Payment payment = getPayment(UuidUtil.parseOrThrow(record.getBody()));
if (payment != null && record instanceof MediaMmsMessageRecord) {
return ((MediaMmsMessageRecord) record).withPayment(payment);
} else {
throw new AssertionError("Payment not found for message");
}
}
return record;
}
@Override
public void remapRecipient(@NonNull RecipientId fromId, @NonNull RecipientId toId) {
ContentValues values = new ContentValues();

View File

@@ -88,7 +88,9 @@ public class SearchDatabase extends Database {
"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 + " " +
"WHERE " + MMS_FTS_TABLE_NAME + " MATCH ? AND " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.MESSAGE_BOX + " & " + MmsSmsColumns.Types.GROUP_V2_BIT + " = 0 " +
"WHERE " + MMS_FTS_TABLE_NAME + " MATCH ? " +
"AND " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.MESSAGE_BOX + " & " + MmsSmsColumns.Types.GROUP_V2_BIT + " = 0 " +
"AND " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.MESSAGE_BOX + " & " + MmsSmsColumns.Types.SPECIAL_TYPE_PAYMENTS_NOTIFICATION + " = 0 " +
"ORDER BY " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " DESC " +
"LIMIT 500";

View File

@@ -52,9 +52,11 @@ 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)) {
} else if (record.isPaymentNotification()) {
return String.format("%s %s", EmojiStrings.CARD, context.getString(R.string.ThreadRecord_payment));
} else if (record.isPaymentsRequestToActivate()) {
return String.format("%s %s", EmojiStrings.CARD, getPaymentActivationRequestSummary(context, record));
} else if (MessageRecordUtil.isPaymentsActivated(record)) {
} else if (record.isPaymentsActivated()) {
return String.format("%s %s", EmojiStrings.CARD, getPaymentActivatedSummary(context, record));
}

View File

@@ -22,7 +22,6 @@ 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;
@@ -233,11 +232,15 @@ public abstract class DisplayRecord {
return SmsDatabase.Types.isPendingInsecureSmsFallbackType(type);
}
public boolean isRequestToActivatePayments() {
return SmsDatabase.Types.isRequestToActivatePayments(type);
public boolean isPaymentNotification() {
return MmsSmsColumns.Types.isPaymentsNotification(type);
}
public boolean isPaymentsRequestToActivate() {
return MmsSmsColumns.Types.isPaymentsRequestToActivate(type);
}
public boolean isPaymentsActivated() {
return SmsDatabase.Types.isPaymentsActivated(type);
return MmsSmsColumns.Types.isPaymentsActivated(type);
}
}

View File

@@ -37,7 +37,9 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge;
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.payments.Payment;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.whispersystems.signalservice.api.payments.FormatterOptions;
import java.util.HashMap;
import java.util.List;
@@ -61,6 +63,7 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
private final int partCount;
private final boolean mentionsSelf;
private final BodyRangeList messageRanges;
private final Payment payment;
public MediaMmsMessageRecord(long id,
Recipient conversationRecipient,
@@ -95,7 +98,8 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
@Nullable BodyRangeList messageRanges,
@NonNull StoryType storyType,
@Nullable ParentStoryId parentStoryId,
@Nullable GiftBadge giftBadge)
@Nullable GiftBadge giftBadge,
@Nullable Payment payment)
{
super(id, body, conversationRecipient, individualRecipient, recipientDeviceId, dateSent,
dateReceived, dateServer, threadId, Status.STATUS_NONE, deliveryReceiptCount, mailbox, mismatches, failures,
@@ -105,6 +109,7 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
this.partCount = partCount;
this.mentionsSelf = mentionsSelf;
this.messageRanges = messageRanges;
this.payment = payment;
}
@Override
@@ -128,6 +133,8 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
return emphasisAdded(context.getString(R.string.MmsMessageRecord_mms_message_encrypted_for_non_existing_session));
} else if (isLegacyMessage()) {
return emphasisAdded(context.getString(R.string.MessageRecord_message_encrypted_with_a_legacy_protocol_version_that_is_no_longer_supported));
} else if (isPaymentNotification() && payment != null) {
return new SpannableString(context.getString(R.string.MessageRecord__payment_s, payment.getAmount().toString(FormatterOptions.defaults())));
}
return super.getDisplayBody(context);
@@ -151,18 +158,22 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
return Objects.requireNonNull(messageRanges);
}
public @Nullable Payment getPayment() {
return payment;
}
public @NonNull MediaMmsMessageRecord withReactions(@NonNull List<ReactionRecord> reactions) {
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
getPartCount(), getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
getReadReceiptCount(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), reactions, isRemoteDelete(), mentionsSelf,
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge());
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment());
}
public @NonNull MediaMmsMessageRecord withoutQuote() {
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
getPartCount(), getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
getReadReceiptCount(), null, getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge());
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment());
}
public @NonNull MediaMmsMessageRecord withAttachments(@NonNull Context context, @NonNull List<DatabaseAttachment> attachments) {
@@ -183,7 +194,14 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), slideDeck,
getPartCount(), getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
getReadReceiptCount(), quote, contacts, linkPreviews, isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge());
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment());
}
public @NonNull MediaMmsMessageRecord withPayment(@NonNull Payment payment) {
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
getPartCount(), getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
getReadReceiptCount(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), payment);
}
private static @NonNull List<Contact> updateContacts(@NonNull List<Contact> contacts, @NonNull Map<AttachmentId, DatabaseAttachment> attachmentIdMap) {

View File

@@ -240,7 +240,7 @@ 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()) {
} else if (isPaymentsRequestToActivate()) {
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()) {
@@ -577,7 +577,7 @@ public abstract class MessageRecord extends DisplayRecord {
isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() ||
isProfileChange() || isGroupV1MigrationEvent() || isChatSessionRefresh() || isBadDecryptType() ||
isChangeNumber() || isBoostRequest() || isThreadMergeEventType() || isSmsExportType() ||
isRequestToActivatePayments() || isPaymentsActivated();
isPaymentsRequestToActivate() || isPaymentsActivated();
}
public boolean isMediaPending() {