mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 17:29:32 +01:00
Add in-chat payment messages.
This commit is contained in:
committed by
Greyson Parrelli
parent
28193c2f61
commit
1dc29fda12
@@ -7,12 +7,14 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.signal.core.util.Stopwatch;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.paging.PagedDataSource;
|
||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationData.MessageRequestData;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationMessage.ConversationMessageFactory;
|
||||
import org.thoughtcrime.securesms.database.MessageDatabase;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.InMemoryMessageRecord;
|
||||
@@ -24,11 +26,12 @@ import org.thoughtcrime.securesms.database.model.ReactionRecord;
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.UpdateDescription;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.payments.Payment;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.signal.core.util.Stopwatch;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -39,6 +42,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -96,6 +100,7 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
||||
MentionHelper mentionHelper = new MentionHelper();
|
||||
AttachmentHelper attachmentHelper = new AttachmentHelper();
|
||||
ReactionHelper reactionHelper = new ReactionHelper();
|
||||
PaymentHelper paymentHelper = new PaymentHelper();
|
||||
Set<ServiceId> referencedIds = new HashSet<>();
|
||||
|
||||
try (MmsSmsDatabase.Reader reader = MmsSmsDatabase.readerFor(db.getConversation(threadId, start, length))) {
|
||||
@@ -105,6 +110,7 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
||||
mentionHelper.add(record);
|
||||
reactionHelper.add(record);
|
||||
attachmentHelper.add(record);
|
||||
paymentHelper.add(record);
|
||||
|
||||
UpdateDescription description = record.getUpdateDisplayBody(context, null);
|
||||
if (description != null) {
|
||||
@@ -138,6 +144,12 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
||||
records = attachmentHelper.buildUpdatedModels(context, records);
|
||||
stopwatch.split("attachment-models");
|
||||
|
||||
paymentHelper.fetchPayments();
|
||||
stopwatch.split("payments");
|
||||
|
||||
records = paymentHelper.buildUpdatedModels(records);
|
||||
stopwatch.split("payment-models");
|
||||
|
||||
for (ServiceId serviceId : referencedIds) {
|
||||
Recipient.resolved(RecipientId.from(serviceId));
|
||||
}
|
||||
@@ -192,6 +204,12 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
||||
|
||||
stopwatch.split("attachments");
|
||||
|
||||
if (record.isPaymentNotification()) {
|
||||
record = SignalDatabase.payments().updateMessageWithPayment(record);
|
||||
}
|
||||
|
||||
stopwatch.split("payments");
|
||||
|
||||
return ConversationMessage.ConversationMessageFactory.createWithUnresolvedData(ApplicationDependencies.getApplication(), record, mentions);
|
||||
} else {
|
||||
return null;
|
||||
@@ -303,4 +321,40 @@ public class ConversationDataSource implements PagedDataSource<MessageId, Conver
|
||||
}
|
||||
}
|
||||
|
||||
private static class PaymentHelper {
|
||||
private final Map<UUID, Long> paymentMessages = new HashMap<>();
|
||||
private final Map<Long, Payment> messageIdToPayment = new HashMap<>();
|
||||
|
||||
public void add(MessageRecord messageRecord) {
|
||||
if (messageRecord.isMms() && messageRecord.isPaymentNotification()) {
|
||||
UUID paymentUuid = UuidUtil.parseOrNull(messageRecord.getBody());
|
||||
if (paymentUuid != null) {
|
||||
paymentMessages.put(paymentUuid, messageRecord.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void fetchPayments() {
|
||||
List<Payment> payments = SignalDatabase.payments().getPayments(paymentMessages.keySet());
|
||||
for (Payment payment : payments) {
|
||||
if (payment != null) {
|
||||
messageIdToPayment.put(paymentMessages.get(payment.getUuid()), payment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull List<MessageRecord> buildUpdatedModels(@NonNull List<MessageRecord> records) {
|
||||
return records.stream()
|
||||
.map(record -> {
|
||||
if (record instanceof MediaMmsMessageRecord) {
|
||||
Payment payment = messageIdToPayment.get(record.getId());
|
||||
if (payment != null) {
|
||||
return ((MediaMmsMessageRecord) record).withPayment(payment);
|
||||
}
|
||||
}
|
||||
return record;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1168,6 +1168,15 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
||||
});
|
||||
}
|
||||
|
||||
private void handleViewPaymentDetails(MessageRecord message) {
|
||||
if (message instanceof MediaMmsMessageRecord) {
|
||||
MediaMmsMessageRecord mediaMessage = (MediaMmsMessageRecord) message;
|
||||
if (mediaMessage.isPaymentNotification() && mediaMessage.getPayment() != null) {
|
||||
startActivity(PaymentsActivity.navigateToPaymentDetails(requireContext(), mediaMessage.getPayment().getUuid()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void performSave(final MediaMmsMessageRecord message) {
|
||||
List<SaveAttachmentTask.Attachment> attachments = Stream.of(message.getSlideDeck().getSlides())
|
||||
.filter(s -> s.getUri() != null && (s.hasImage() || s.hasVideo() || s.hasAudio() || s.hasDocument()))
|
||||
@@ -2287,6 +2296,9 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
||||
case COPY:
|
||||
handleCopyMessage(conversationMessage.getMultiselectCollection().toSet());
|
||||
break;
|
||||
case PAYMENT_DETAILS:
|
||||
handleViewPaymentDetails(conversationMessage.getMessageRecord());
|
||||
break;
|
||||
case MULTISELECT:
|
||||
handleEnterMultiSelect(conversationMessage);
|
||||
break;
|
||||
|
||||
@@ -95,6 +95,7 @@ import org.thoughtcrime.securesms.conversation.colors.ChatColors;
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer;
|
||||
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectCollection;
|
||||
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectPart;
|
||||
import org.thoughtcrime.securesms.conversation.ui.payment.PaymentMessageView;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.database.MediaDatabase;
|
||||
import org.thoughtcrime.securesms.database.MessageDatabase;
|
||||
@@ -181,14 +182,14 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
private static final long MAX_CLUSTERING_TIME_DIFF = TimeUnit.MINUTES.toMillis(3);
|
||||
private static final int CONDENSED_MODE_MAX_LINES = 3;
|
||||
|
||||
private ConversationMessage conversationMessage;
|
||||
private MessageRecord messageRecord;
|
||||
private Optional<MessageRecord> nextMessageRecord;
|
||||
private Locale locale;
|
||||
private boolean groupThread;
|
||||
private LiveRecipient recipient;
|
||||
private GlideRequests glideRequests;
|
||||
private ValueAnimator pulseOutlinerAlphaAnimator;
|
||||
private ConversationMessage conversationMessage;
|
||||
private MessageRecord messageRecord;
|
||||
private Optional<MessageRecord> nextMessageRecord;
|
||||
private Locale locale;
|
||||
private boolean groupThread;
|
||||
private LiveRecipient recipient;
|
||||
private GlideRequests glideRequests;
|
||||
private ValueAnimator pulseOutlinerAlphaAnimator;
|
||||
private Optional<MessageRecord> previousMessage;
|
||||
private ConversationItemDisplayMode displayMode;
|
||||
|
||||
@@ -224,6 +225,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
private Stub<ViewOnceMessageView> revealableStub;
|
||||
private Stub<Button> callToActionStub;
|
||||
private Stub<GiftMessageView> giftViewStub;
|
||||
private Stub<PaymentMessageView> paymentViewStub;
|
||||
private @Nullable EventListener eventListener;
|
||||
|
||||
private int defaultBubbleColor;
|
||||
@@ -325,6 +327,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
this.storyReactionLabel = findViewById(R.id.story_reacted_label);
|
||||
this.giftViewStub = new Stub<>(findViewById(R.id.gift_view_stub));
|
||||
this.quotedIndicator = findViewById(R.id.quoted_indicator);
|
||||
this.paymentViewStub = new Stub<>(findViewById(R.id.payment_view_stub));
|
||||
|
||||
setOnClickListener(new ClickListener(null));
|
||||
|
||||
@@ -1000,7 +1003,9 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
bodyText.setText(italics);
|
||||
bodyText.setVisibility(View.VISIBLE);
|
||||
bodyText.setOverflowText(null);
|
||||
} else if (isCaptionlessMms(messageRecord) || isStoryReaction(messageRecord) || isGiftMessage(messageRecord)) {
|
||||
} else if (isCaptionlessMms(messageRecord) || isStoryReaction(messageRecord) || isGiftMessage(messageRecord) || messageRecord.isPaymentNotification()) {
|
||||
bodyText.setText(null);
|
||||
bodyText.setOverflowText(null);
|
||||
bodyText.setVisibility(View.GONE);
|
||||
} else {
|
||||
Spannable styledText = conversationMessage.getDisplayBody(getContext());
|
||||
@@ -1076,6 +1081,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE);
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (giftViewStub.resolved()) giftViewStub.get().setVisibility(View.GONE);
|
||||
paymentViewStub.setVisibility(View.GONE);
|
||||
|
||||
revealableStub.get().setMessage((MmsMessageRecord) messageRecord, hasWallpaper);
|
||||
revealableStub.get().setOnClickListener(revealableClickListener);
|
||||
@@ -1093,6 +1099,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (revealableStub.resolved()) revealableStub.get().setVisibility(View.GONE);
|
||||
if (giftViewStub.resolved()) giftViewStub.get().setVisibility(View.GONE);
|
||||
paymentViewStub.setVisibility(View.GONE);
|
||||
|
||||
sharedContactStub.get().setContact(((MediaMmsMessageRecord) messageRecord).getSharedContacts().get(0), glideRequests, locale);
|
||||
sharedContactStub.get().setEventListener(sharedContactEventListener);
|
||||
@@ -1113,6 +1120,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (revealableStub.resolved()) revealableStub.get().setVisibility(View.GONE);
|
||||
if (giftViewStub.resolved()) giftViewStub.get().setVisibility(View.GONE);
|
||||
paymentViewStub.setVisibility(View.GONE);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0);
|
||||
@@ -1160,6 +1168,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (revealableStub.resolved()) revealableStub.get().setVisibility(View.GONE);
|
||||
if (giftViewStub.resolved()) giftViewStub.get().setVisibility(View.GONE);
|
||||
paymentViewStub.setVisibility(View.GONE);
|
||||
|
||||
audioViewStub.get().setAudio(Objects.requireNonNull(((MediaMmsMessageRecord) messageRecord).getSlideDeck().getAudioSlide()), new AudioViewCallbacks(), showControls, true);
|
||||
audioViewStub.get().setDownloadClickListener(singleDownloadClickListener);
|
||||
@@ -1186,6 +1195,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (revealableStub.resolved()) revealableStub.get().setVisibility(View.GONE);
|
||||
if (giftViewStub.resolved()) giftViewStub.get().setVisibility(View.GONE);
|
||||
paymentViewStub.setVisibility(View.GONE);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
documentViewStub.get().setDocument(
|
||||
@@ -1213,6 +1223,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE);
|
||||
if (revealableStub.resolved()) revealableStub.get().setVisibility(View.GONE);
|
||||
if (giftViewStub.resolved()) giftViewStub.get().setVisibility(View.GONE);
|
||||
paymentViewStub.setVisibility(View.GONE);
|
||||
|
||||
if (hasSticker(messageRecord)) {
|
||||
//noinspection ConstantConditions
|
||||
@@ -1243,6 +1254,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (revealableStub.resolved()) revealableStub.get().setVisibility(View.GONE);
|
||||
if (giftViewStub.resolved()) giftViewStub.get().setVisibility(View.GONE);
|
||||
paymentViewStub.setVisibility(View.GONE);
|
||||
|
||||
List<Slide> thumbnailSlides = ((MmsMessageRecord) messageRecord).getSlideDeck().getThumbnailSlides();
|
||||
mediaThumbnailStub.require().setMinimumThumbnailWidth(readDimen(isCaptionlessMms(messageRecord) ? R.dimen.media_bubble_min_width_solo
|
||||
@@ -1296,11 +1308,28 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE);
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(GONE);
|
||||
if (revealableStub.resolved()) revealableStub.get().setVisibility(GONE);
|
||||
paymentViewStub.setVisibility(View.GONE);
|
||||
|
||||
MmsMessageRecord mmsMessageRecord = (MmsMessageRecord) messageRecord;
|
||||
giftViewStub.get().setGiftBadge(glideRequests, Objects.requireNonNull(mmsMessageRecord.getGiftBadge()), messageRecord.isOutgoing(), giftMessageViewCallback);
|
||||
giftViewStub.get().setVisibility(VISIBLE);
|
||||
|
||||
footer.setVisibility(VISIBLE);
|
||||
} else if (messageRecord.isPaymentNotification()) {
|
||||
if (mediaThumbnailStub.resolved()) mediaThumbnailStub.require().setVisibility(GONE);
|
||||
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(GONE);
|
||||
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(GONE);
|
||||
if (sharedContactStub.resolved()) sharedContactStub.get().setVisibility(GONE);
|
||||
if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE);
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(GONE);
|
||||
if (revealableStub.resolved()) revealableStub.get().setVisibility(GONE);
|
||||
if (giftViewStub.resolved()) giftViewStub.get().setVisibility(View.GONE);
|
||||
|
||||
MediaMmsMessageRecord mediaMmsMessageRecord = (MediaMmsMessageRecord) messageRecord;
|
||||
|
||||
paymentViewStub.setVisibility(View.VISIBLE);
|
||||
paymentViewStub.get().bindPayment(messageRecord.getIndividualRecipient(), Objects.requireNonNull(mediaMmsMessageRecord.getPayment()), colorizer);
|
||||
|
||||
footer.setVisibility(VISIBLE);
|
||||
} else {
|
||||
if (mediaThumbnailStub.resolved()) mediaThumbnailStub.require().setVisibility(View.GONE);
|
||||
@@ -1311,6 +1340,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (revealableStub.resolved()) revealableStub.get().setVisibility(View.GONE);
|
||||
if (giftViewStub.resolved()) giftViewStub.get().setVisibility(View.GONE);
|
||||
paymentViewStub.setVisibility(View.GONE);
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParamsIfNonNull(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
|
||||
@@ -761,6 +761,10 @@ public final class ConversationReactionOverlay extends FrameLayout {
|
||||
items.add(new ActionItem(R.drawable.ic_copy_24_tinted, getResources().getString(R.string.conversation_selection__menu_copy), () -> handleActionItemClicked(Action.COPY)));
|
||||
}
|
||||
|
||||
if (menuState.shouldShowPaymentDetails()) {
|
||||
items.add(new ActionItem(R.drawable.ic_payments_24, getResources().getString(R.string.conversation_selection__menu_payment_details), () -> handleActionItemClicked(Action.PAYMENT_DETAILS)));
|
||||
}
|
||||
|
||||
items.add(new ActionItem(R.drawable.ic_select_24_tinted, getResources().getString(R.string.conversation_selection__menu_multi_select), () -> handleActionItemClicked(Action.MULTISELECT)));
|
||||
|
||||
if (menuState.shouldShowDetailsAction()) {
|
||||
@@ -976,6 +980,7 @@ public final class ConversationReactionOverlay extends FrameLayout {
|
||||
DOWNLOAD,
|
||||
COPY,
|
||||
MULTISELECT,
|
||||
PAYMENT_DETAILS,
|
||||
VIEW_INFO,
|
||||
DELETE,
|
||||
}
|
||||
|
||||
@@ -544,7 +544,7 @@ public final class ConversationUpdateItem extends FrameLayout
|
||||
});
|
||||
|
||||
actionButton.setText(R.string.ConversationActivity__invite_to_signal);
|
||||
} else if (conversationMessage.getMessageRecord().isRequestToActivatePayments() && !conversationMessage.getMessageRecord().isOutgoing() && !SignalStore.paymentsValues().mobileCoinPaymentsEnabled()) {
|
||||
} else if (conversationMessage.getMessageRecord().isPaymentsRequestToActivate() && !conversationMessage.getMessageRecord().isOutgoing() && !SignalStore.paymentsValues().mobileCoinPaymentsEnabled()) {
|
||||
actionButton.setText(R.string.ConversationUpdateItem_activate_payments);
|
||||
actionButton.setVisibility(VISIBLE);
|
||||
actionButton.setOnClickListener(v -> {
|
||||
|
||||
@@ -24,6 +24,7 @@ final class MenuState {
|
||||
private final boolean copy;
|
||||
private final boolean delete;
|
||||
private final boolean reactions;
|
||||
private final boolean paymentDetails;
|
||||
|
||||
private MenuState(@NonNull Builder builder) {
|
||||
forward = builder.forward;
|
||||
@@ -34,6 +35,7 @@ final class MenuState {
|
||||
copy = builder.copy;
|
||||
delete = builder.delete;
|
||||
reactions = builder.reactions;
|
||||
paymentDetails = builder.paymentDetails;
|
||||
}
|
||||
|
||||
boolean shouldShowForwardAction() {
|
||||
@@ -68,6 +70,10 @@ final class MenuState {
|
||||
return reactions;
|
||||
}
|
||||
|
||||
boolean shouldShowPaymentDetails() {
|
||||
return paymentDetails;
|
||||
}
|
||||
|
||||
static MenuState getMenuState(@NonNull Recipient conversationRecipient,
|
||||
@NonNull Set<MultiselectPart> selectedParts,
|
||||
boolean shouldShowMessageRequest,
|
||||
@@ -84,6 +90,7 @@ final class MenuState {
|
||||
boolean hasPendingMedia = false;
|
||||
boolean mediaIsSelected = false;
|
||||
boolean hasGift = false;
|
||||
boolean hasPayment = false;
|
||||
|
||||
for (MultiselectPart part : selectedParts) {
|
||||
MessageRecord messageRecord = part.getMessageRecord();
|
||||
@@ -121,6 +128,10 @@ final class MenuState {
|
||||
if (MessageRecordUtil.hasGiftBadge(messageRecord)) {
|
||||
hasGift = true;
|
||||
}
|
||||
|
||||
if (messageRecord.isPaymentNotification()) {
|
||||
hasPayment = true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean shouldShowForwardAction = !actionMessage &&
|
||||
@@ -129,6 +140,7 @@ final class MenuState {
|
||||
!remoteDelete &&
|
||||
!hasPendingMedia &&
|
||||
!hasGift &&
|
||||
!hasPayment &&
|
||||
selectedParts.size() <= MAX_FORWARDABLE_COUNT;
|
||||
|
||||
int uniqueRecords = selectedParts.stream()
|
||||
@@ -160,9 +172,10 @@ final class MenuState {
|
||||
.shouldShowReplyAction(canReplyToMessage(conversationRecipient, actionMessage, messageRecord, shouldShowMessageRequest, isNonAdminInAnnouncementGroup));
|
||||
}
|
||||
|
||||
return builder.shouldShowCopyAction(!actionMessage && !remoteDelete && hasText && !hasGift)
|
||||
return builder.shouldShowCopyAction(!actionMessage && !remoteDelete && hasText && !hasGift && !hasPayment)
|
||||
.shouldShowDeleteAction(!hasInMemory && onlyContainsCompleteMessages(selectedParts))
|
||||
.shouldShowReactions(!conversationRecipient.isReleaseNotes())
|
||||
.shouldShowPaymentDetails(hasPayment)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -206,7 +219,7 @@ final class MenuState {
|
||||
messageRecord.isInMemoryMessageRecord() ||
|
||||
messageRecord.isChangeNumber() ||
|
||||
messageRecord.isBoostRequest() ||
|
||||
messageRecord.isRequestToActivatePayments() ||
|
||||
messageRecord.isPaymentsRequestToActivate() ||
|
||||
messageRecord.isPaymentsActivated();
|
||||
}
|
||||
|
||||
@@ -220,6 +233,7 @@ final class MenuState {
|
||||
private boolean copy;
|
||||
private boolean delete;
|
||||
private boolean reactions;
|
||||
private boolean paymentDetails;
|
||||
|
||||
@NonNull Builder shouldShowForwardAction(boolean forward) {
|
||||
this.forward = forward;
|
||||
@@ -261,6 +275,11 @@ final class MenuState {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull Builder shouldShowPaymentDetails(boolean paymentDetails) {
|
||||
this.paymentDetails = paymentDetails;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
MenuState build() {
|
||||
return new MenuState(this);
|
||||
|
||||
@@ -46,7 +46,7 @@ class MessageQuotesRepository {
|
||||
|
||||
@WorkerThread
|
||||
private fun getMessageInQuoteChainSync(application: Application, messageId: MessageId): List<ConversationMessage> {
|
||||
val originalRecord: MessageRecord? = if (messageId.mms) {
|
||||
var originalRecord: MessageRecord? = if (messageId.mms) {
|
||||
SignalDatabase.mms.getMessageRecordOrNull(messageId.id)
|
||||
} else {
|
||||
SignalDatabase.sms.getMessageRecordOrNull(messageId.id)
|
||||
@@ -66,7 +66,7 @@ class MessageQuotesRepository {
|
||||
.buildUpdatedModels(replyRecords)
|
||||
.map { replyRecord ->
|
||||
val replyQuote: Quote? = replyRecord.getQuote()
|
||||
if (replyQuote != null && replyQuote.id == originalRecord.dateSent) {
|
||||
if (replyQuote != null && replyQuote.id == originalRecord!!.dateSent) {
|
||||
(replyRecord as MediaMmsMessageRecord).withoutQuote()
|
||||
} else {
|
||||
replyRecord
|
||||
@@ -74,6 +74,10 @@ class MessageQuotesRepository {
|
||||
}
|
||||
.map { ConversationMessageFactory.createWithUnresolvedData(application, it) }
|
||||
|
||||
if (originalRecord.isPaymentNotification) {
|
||||
originalRecord = SignalDatabase.payments.updateMessageWithPayment(originalRecord)
|
||||
}
|
||||
|
||||
val originalMessage: List<ConversationMessage> = ConversationDataSource.ReactionHelper()
|
||||
.apply {
|
||||
add(originalRecord)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.thoughtcrime.securesms.conversation.ui.payment
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.text.style.TypefaceSpan
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.ViewCompat
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.quotes.QuoteViewColorTheme
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer
|
||||
import org.thoughtcrime.securesms.databinding.PaymentMessageViewBinding
|
||||
import org.thoughtcrime.securesms.payments.Direction
|
||||
import org.thoughtcrime.securesms.payments.Payment
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
|
||||
/**
|
||||
* Showing payment information in conversation.
|
||||
*/
|
||||
class PaymentMessageView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) : FrameLayout(context, attrs) {
|
||||
|
||||
private val binding: PaymentMessageViewBinding
|
||||
|
||||
init {
|
||||
binding = PaymentMessageViewBinding.inflate(LayoutInflater.from(context), this, true)
|
||||
}
|
||||
|
||||
fun bindPayment(recipient: Recipient, payment: Payment, colorizer: Colorizer) {
|
||||
val outgoing = payment.direction == Direction.SENT
|
||||
|
||||
binding.paymentDirection.apply {
|
||||
if (outgoing) {
|
||||
text = context.getString(R.string.PaymentMessageView_you_sent_s, recipient.getShortDisplayName(context))
|
||||
setTextColor(colorizer.getOutgoingFooterTextColor(context))
|
||||
} else {
|
||||
text = context.getString(R.string.PaymentMessageView_s_sent_you, recipient.getShortDisplayName(context))
|
||||
setTextColor(colorizer.getIncomingFooterTextColor(context, recipient.hasWallpaper()))
|
||||
}
|
||||
}
|
||||
|
||||
binding.paymentNote.apply {
|
||||
text = payment.note
|
||||
visible = payment.note.isNotEmpty()
|
||||
setTextColor(if (outgoing) colorizer.getOutgoingBodyTextColor(context) else colorizer.getIncomingBodyTextColor(context, recipient.hasWallpaper()))
|
||||
}
|
||||
|
||||
val quoteViewColorTheme = QuoteViewColorTheme.resolveTheme(outgoing, false, recipient.hasWallpaper())
|
||||
|
||||
binding.paymentAmount.setTextColor(quoteViewColorTheme.getForegroundColor(context))
|
||||
binding.paymentAmount.setMoney(payment.amount, 0L, currencyTypefaceSpan)
|
||||
|
||||
ViewCompat.setBackgroundTintList(binding.paymentAmountLayout, ColorStateList.valueOf(quoteViewColorTheme.getBackgroundColor(context)))
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val currencyTypefaceSpan = TypefaceSpan("sans-serif-light")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user