Add support for replying to gift badges.

This commit is contained in:
Alex Hart
2022-05-10 10:10:35 -03:00
parent 0c1edd6a56
commit 8ca0f4baf4
22 changed files with 247 additions and 54 deletions

View File

@@ -179,9 +179,10 @@ public class InputPanel extends LinearLayout
long id,
@NonNull Recipient author,
@NonNull CharSequence body,
@NonNull SlideDeck attachments)
@NonNull SlideDeck attachments,
@NonNull QuoteModel.Type quoteType)
{
this.quoteView.setQuote(glideRequests, id, author, body, false, attachments, null, null);
this.quoteView.setQuote(glideRequests, id, author, body, false, attachments, null, null, quoteType);
int originalHeight = this.quoteView.getVisibility() == VISIBLE ? this.quoteView.getMeasuredHeight()
: 0;
@@ -256,7 +257,7 @@ public class InputPanel extends LinearLayout
public Optional<QuoteModel> getQuote() {
if (quoteView.getQuoteId() > 0 && quoteView.getVisibility() == View.VISIBLE) {
return Optional.of(new QuoteModel(quoteView.getQuoteId(), quoteView.getAuthor().getId(), quoteView.getBody().toString(), false, quoteView.getAttachments(), quoteView.getMentions()));
return Optional.of(new QuoteModel(quoteView.getQuoteId(), quoteView.getAuthor().getId(), quoteView.getBody().toString(), false, quoteView.getAttachments(), quoteView.getMentions(), quoteView.getQuoteType()));
} else {
return Optional.empty();
}

View File

@@ -17,6 +17,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.ContextCompat;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
@@ -30,6 +31,7 @@ import org.thoughtcrime.securesms.conversation.colors.ChatColors;
import org.thoughtcrime.securesms.database.model.Mention;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.QuoteModel;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.LiveRecipient;
@@ -87,16 +89,17 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
private EmojiImageView missingStoryReaction;
private EmojiImageView storyReactionEmoji;
private long id;
private LiveRecipient author;
private CharSequence body;
private TextView mediaDescriptionText;
private TextView missingLinkText;
private SlideDeck attachments;
private MessageType messageType;
private int largeCornerRadius;
private int smallCornerRadius;
private CornerMask cornerMask;
private long id;
private LiveRecipient author;
private CharSequence body;
private TextView mediaDescriptionText;
private TextView missingLinkText;
private SlideDeck attachments;
private MessageType messageType;
private int largeCornerRadius;
private int smallCornerRadius;
private CornerMask cornerMask;
private QuoteModel.Type quoteType;
private int thumbHeight;
private int thumbWidth;
@@ -206,7 +209,8 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
boolean originalMissing,
@NonNull SlideDeck attachments,
@Nullable ChatColors chatColors,
@Nullable String storyReaction)
@Nullable String storyReaction,
@NonNull QuoteModel.Type quoteType)
{
if (this.author != null) this.author.removeForeverObserver(this);
@@ -214,10 +218,11 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
this.author = author.live();
this.body = body;
this.attachments = attachments;
this.quoteType = quoteType;
this.author.observeForever(this);
setQuoteAuthor(author);
setQuoteText(body, attachments, originalMissing, storyReaction);
setQuoteText(resolveBody(body, quoteType), attachments, originalMissing, storyReaction);
setQuoteAttachment(glideRequests, body, attachments, originalMissing);
setQuoteMissingFooter(originalMissing);
@@ -228,6 +233,10 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
}
}
private @Nullable CharSequence resolveBody(@Nullable CharSequence body, @NonNull QuoteModel.Type quoteType) {
return quoteType == QuoteModel.Type.GIFT_BADGE ? getContext().getString(R.string.QuoteView__gift) : body;
}
public void setTopCornerSizes(boolean topLeftLarge, boolean topRightLarge) {
cornerMask.setTopLeftRadius(topLeftLarge ? largeCornerRadius : smallCornerRadius);
cornerMask.setTopRightRadius(topRightLarge ? largeCornerRadius : smallCornerRadius);
@@ -386,6 +395,18 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
return;
}
if (quoteType == QuoteModel.Type.GIFT_BADGE) {
attachmentVideoOverlayView.setVisibility(GONE);
attachmentContainerView.setVisibility(GONE);
thumbnailView.setVisibility(VISIBLE);
glideRequests.load(R.drawable.ic_gift_thumbnail)
.centerCrop()
.override(thumbWidth, thumbHeight)
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.into(thumbnailView);
return;
}
Slide imageVideoSlide = slideDeck.getSlides().stream().filter(s -> s.hasImage() || s.hasVideo() || s.hasSticker()).findFirst().orElse(null);
Slide documentSlide = slideDeck.getSlides().stream().filter(Slide::hasDocument).findFirst().orElse(null);
Slide viewOnceSlide = slideDeck.getSlides().stream().filter(Slide::hasViewOnce).findFirst().orElse(null);
@@ -459,6 +480,10 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
return attachments.asAttachments();
}
public @NonNull QuoteModel.Type getQuoteType() {
return quoteType;
}
public @NonNull List<Mention> getMentions() {
return MentionAnnotation.getMentionsFromAnnotations(body);
}

View File

@@ -1471,7 +1471,8 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
quote.isOriginalMissing(),
quote.getAttachment(),
chatColors,
isStoryReaction(current) ? current.getBody() : null);
isStoryReaction(current) ? current.getBody() : null,
quote.getQuoteType());
quoteView.setVisibility(View.VISIBLE);
quoteView.setTextSize(TypedValue.COMPLEX_UNIT_SP, SignalStore.settings().getMessageFontSize());

View File

@@ -281,6 +281,7 @@ import org.thoughtcrime.securesms.util.FullscreenHelper;
import org.thoughtcrime.securesms.util.IdentityUtil;
import org.thoughtcrime.securesms.util.LifecycleDisposable;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.MessageRecordUtil;
import org.thoughtcrime.securesms.util.MessageUtil;
import org.thoughtcrime.securesms.util.PlayStoreUtil;
import org.thoughtcrime.securesms.util.ServiceUtil;
@@ -3876,7 +3877,8 @@ public class ConversationParentFragment extends Fragment
messageRecord.getDateSent(),
author,
body,
slideDeck);
slideDeck,
MessageRecordUtil.getRecordQuoteType(messageRecord));
} else if (messageRecord.isMms() && !((MmsMessageRecord) messageRecord).getLinkPreviews().isEmpty()) {
LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0);
@@ -3890,7 +3892,8 @@ public class ConversationParentFragment extends Fragment
messageRecord.getDateSent(),
author,
conversationMessage.getDisplayBody(requireContext()),
slideDeck);
slideDeck,
MessageRecordUtil.getRecordQuoteType(messageRecord));
} else {
SlideDeck slideDeck = messageRecord.isMms() ? ((MmsMessageRecord) messageRecord).getSlideDeck() : new SlideDeck();
@@ -3904,7 +3907,8 @@ public class ConversationParentFragment extends Fragment
messageRecord.getDateSent(),
author,
conversationMessage.getDisplayBody(requireContext()),
slideDeck);
slideDeck,
MessageRecordUtil.getRecordQuoteType(messageRecord));
}
inputPanel.clickOnComposeInput();

View File

@@ -188,7 +188,6 @@ final class MenuState {
messageRecord.isSecure() &&
(!conversationRecipient.isGroup() || conversationRecipient.isActiveGroup()) &&
!messageRecord.getRecipient().isBlocked() &&
!MessageRecordUtil.hasGiftBadge(messageRecord) &&
!conversationRecipient.isReleaseNotes();
}

View File

@@ -130,6 +130,7 @@ public class MmsDatabase extends MessageDatabase {
static final String QUOTE_ATTACHMENT = "quote_attachment";
static final String QUOTE_MISSING = "quote_missing";
static final String QUOTE_MENTIONS = "quote_mentions";
static final String QUOTE_TYPE = "quote_type";
static final String SHARED_CONTACTS = "shared_contacts";
static final String LINK_PREVIEWS = "previews";
@@ -171,6 +172,7 @@ public class MmsDatabase extends MessageDatabase {
QUOTE_ATTACHMENT + " INTEGER DEFAULT -1, " +
QUOTE_MISSING + " INTEGER DEFAULT 0, " +
QUOTE_MENTIONS + " BLOB DEFAULT NULL," +
QUOTE_TYPE + " INTEGER DEFAULT 0," +
SHARED_CONTACTS + " TEXT, " +
UNIDENTIFIED + " INTEGER DEFAULT 0, " +
LINK_PREVIEWS + " TEXT, " +
@@ -209,7 +211,7 @@ public class MmsDatabase extends MessageDatabase {
MESSAGE_SIZE, STATUS, TRANSACTION_ID,
BODY, PART_COUNT, RECIPIENT_ID, ADDRESS_DEVICE_ID,
DELIVERY_RECEIPT_COUNT, READ_RECEIPT_COUNT, MISMATCHED_IDENTITIES, NETWORK_FAILURE, SUBSCRIPTION_ID,
EXPIRES_IN, EXPIRE_STARTED, NOTIFIED, QUOTE_ID, QUOTE_AUTHOR, QUOTE_BODY, QUOTE_ATTACHMENT, QUOTE_MISSING, QUOTE_MENTIONS,
EXPIRES_IN, EXPIRE_STARTED, NOTIFIED, QUOTE_ID, QUOTE_AUTHOR, QUOTE_BODY, QUOTE_ATTACHMENT, QUOTE_TYPE, QUOTE_MISSING, QUOTE_MENTIONS,
SHARED_CONTACTS, LINK_PREVIEWS, UNIDENTIFIED, VIEW_ONCE, REACTIONS_UNREAD, REACTIONS_LAST_SEEN,
REMOTE_DELETED, MENTIONS_SELF, NOTIFIED_TIMESTAMP, VIEWED_RECEIPT_COUNT, RECEIPT_TIMESTAMP, MESSAGE_RANGES,
STORY_TYPE, PARENT_STORY_ID,
@@ -1216,6 +1218,7 @@ public class MmsDatabase extends MessageDatabase {
values.putNull(QUOTE_BODY);
values.putNull(QUOTE_AUTHOR);
values.putNull(QUOTE_ATTACHMENT);
values.putNull(QUOTE_TYPE);
values.putNull(QUOTE_ID);
values.putNull(LINK_PREVIEWS);
values.putNull(SHARED_CONTACTS);
@@ -1536,6 +1539,7 @@ public class MmsDatabase extends MessageDatabase {
long quoteId = cursor.getLong(cursor.getColumnIndexOrThrow(QUOTE_ID));
long quoteAuthor = cursor.getLong(cursor.getColumnIndexOrThrow(QUOTE_AUTHOR));
String quoteText = cursor.getString(cursor.getColumnIndexOrThrow(QUOTE_BODY));
int quoteType = cursor.getInt(cursor.getColumnIndexOrThrow(QUOTE_TYPE));
boolean quoteMissing = cursor.getInt(cursor.getColumnIndexOrThrow(QUOTE_MISSING)) == 1;
List<Attachment> quoteAttachments = Stream.of(associatedAttachments).filter(Attachment::isQuote).map(a -> (Attachment)a).toList();
List<Mention> quoteMentions = parseQuoteMentions(context, cursor);
@@ -1555,7 +1559,7 @@ public class MmsDatabase extends MessageDatabase {
QuoteModel quote = null;
if (quoteId > 0 && quoteAuthor > 0 && (!TextUtils.isEmpty(quoteText) || !quoteAttachments.isEmpty())) {
quote = new QuoteModel(quoteId, RecipientId.from(quoteAuthor), quoteText, quoteMissing, quoteAttachments, quoteMentions);
quote = new QuoteModel(quoteId, RecipientId.from(quoteAuthor), quoteText, quoteMissing, quoteAttachments, quoteMentions, QuoteModel.Type.fromCode(quoteType));
}
if (!TextUtils.isEmpty(mismatchDocument)) {
@@ -1739,6 +1743,7 @@ public class MmsDatabase extends MessageDatabase {
contentValues.put(QUOTE_ID, retrieved.getQuote().getId());
contentValues.put(QUOTE_BODY, retrieved.getQuote().getText().toString());
contentValues.put(QUOTE_AUTHOR, retrieved.getQuote().getAuthor().serialize());
contentValues.put(QUOTE_TYPE, retrieved.getQuote().getType().getCode());
contentValues.put(QUOTE_MISSING, retrieved.getQuote().isOriginalMissing() ? 1 : 0);
BodyRangeList mentionsList = MentionUtil.mentionsToBodyRangeList(retrieved.getQuote().getMentions());
@@ -2011,6 +2016,7 @@ public class MmsDatabase extends MessageDatabase {
contentValues.put(QUOTE_ID, message.getOutgoingQuote().getId());
contentValues.put(QUOTE_AUTHOR, message.getOutgoingQuote().getAuthor().serialize());
contentValues.put(QUOTE_BODY, updated.getBodyAsString());
contentValues.put(QUOTE_TYPE, message.getOutgoingQuote().getType().getCode());
contentValues.put(QUOTE_MISSING, message.getOutgoingQuote().isOriginalMissing() ? 1 : 0);
BodyRangeList mentionsList = MentionUtil.mentionsToBodyRangeList(updated.getMentions());
@@ -2485,7 +2491,8 @@ public class MmsDatabase extends MessageDatabase {
quoteText,
message.getOutgoingQuote().isOriginalMissing(),
new SlideDeck(context, message.getOutgoingQuote().getAttachments()),
quoteMentions) :
quoteMentions,
message.getOutgoingQuote().getType()) :
null,
message.getSharedContacts(),
message.getLinkPreviews(),
@@ -2699,6 +2706,7 @@ public class MmsDatabase extends MessageDatabase {
long quoteId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.QUOTE_ID));
long quoteAuthor = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.QUOTE_AUTHOR));
CharSequence quoteText = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.QUOTE_BODY));
int quoteType = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.QUOTE_TYPE));
boolean quoteMissing = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.QUOTE_MISSING)) == 1;
List<Mention> quoteMentions = parseQuoteMentions(context, cursor);
List<DatabaseAttachment> attachments = SignalDatabase.attachments().getAttachments(cursor);
@@ -2713,7 +2721,7 @@ public class MmsDatabase extends MessageDatabase {
quoteMentions = updated.getMentions();
}
return new Quote(quoteId, RecipientId.from(quoteAuthor), quoteText, quoteMissing, quoteDeck, quoteMentions);
return new Quote(quoteId, RecipientId.from(quoteAuthor), quoteText, quoteMissing, quoteDeck, quoteMentions, QuoteModel.Type.fromCode(quoteType));
} else {
return null;
}

View File

@@ -99,6 +99,7 @@ public class MmsSmsDatabase extends Database {
MmsDatabase.QUOTE_BODY,
MmsDatabase.QUOTE_MISSING,
MmsDatabase.QUOTE_ATTACHMENT,
MmsDatabase.QUOTE_TYPE,
MmsDatabase.QUOTE_MENTIONS,
MmsDatabase.SHARED_CONTACTS,
MmsDatabase.LINK_PREVIEWS,
@@ -777,6 +778,7 @@ public class MmsSmsDatabase extends Database {
MmsDatabase.QUOTE_BODY,
MmsDatabase.QUOTE_MISSING,
MmsDatabase.QUOTE_ATTACHMENT,
MmsDatabase.QUOTE_TYPE,
MmsDatabase.QUOTE_MENTIONS,
MmsDatabase.SHARED_CONTACTS,
MmsDatabase.LINK_PREVIEWS,
@@ -813,6 +815,7 @@ public class MmsSmsDatabase extends Database {
MmsDatabase.QUOTE_BODY,
MmsDatabase.QUOTE_MISSING,
MmsDatabase.QUOTE_ATTACHMENT,
MmsDatabase.QUOTE_TYPE,
MmsDatabase.QUOTE_MENTIONS,
MmsDatabase.SHARED_CONTACTS,
MmsDatabase.LINK_PREVIEWS,
@@ -878,6 +881,7 @@ public class MmsSmsDatabase extends Database {
mmsColumnsPresent.add(MmsDatabase.QUOTE_BODY);
mmsColumnsPresent.add(MmsDatabase.QUOTE_MISSING);
mmsColumnsPresent.add(MmsDatabase.QUOTE_ATTACHMENT);
mmsColumnsPresent.add(MmsDatabase.QUOTE_TYPE);
mmsColumnsPresent.add(MmsDatabase.QUOTE_MENTIONS);
mmsColumnsPresent.add(MmsDatabase.SHARED_CONTACTS);
mmsColumnsPresent.add(MmsDatabase.LINK_PREVIEWS);

View File

@@ -195,8 +195,9 @@ object SignalDatabaseMigrations {
private const val REMOVE_KNOWN_UNKNOWNS = 139
private const val CDS_V2 = 140
private const val GROUP_SERVICE_ID = 141
private const val QUOTE_TYPE = 142
const val DATABASE_VERSION = 141
const val DATABASE_VERSION = 142
@JvmStatic
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
@@ -2528,6 +2529,10 @@ object SignalDatabaseMigrations {
if (oldVersion < GROUP_SERVICE_ID) {
db.execSQL("ALTER TABLE groups ADD COLUMN auth_service_id TEXT DEFAULT NULL")
}
if (oldVersion < QUOTE_TYPE) {
db.execSQL("ALTER TABLE mms ADD COLUMN quote_type INTEGER DEFAULT 0")
}
}
@JvmStatic

View File

@@ -6,6 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.components.mention.MentionAnnotation;
import org.thoughtcrime.securesms.mms.QuoteModel;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.RecipientId;
@@ -13,25 +14,28 @@ import java.util.List;
public class Quote {
private final long id;
private final RecipientId author;
private final CharSequence text;
private final boolean missing;
private final SlideDeck attachment;
private final List<Mention> mentions;
private final long id;
private final RecipientId author;
private final CharSequence text;
private final boolean missing;
private final SlideDeck attachment;
private final List<Mention> mentions;
private final QuoteModel.Type quoteType;
public Quote(long id,
@NonNull RecipientId author,
@Nullable CharSequence text,
boolean missing,
@NonNull SlideDeck attachment,
@NonNull List<Mention> mentions)
@NonNull List<Mention> mentions,
@NonNull QuoteModel.Type quoteType)
{
this.id = id;
this.author = author;
this.missing = missing;
this.attachment = attachment;
this.mentions = mentions;
this.id = id;
this.author = author;
this.missing = missing;
this.attachment = attachment;
this.mentions = mentions;
this.quoteType = quoteType;
SpannableString spannable = new SpannableString(text);
MentionAnnotation.setMentionAnnotations(spannable, mentions);
@@ -40,7 +44,7 @@ public class Quote {
}
public @NonNull Quote withAttachment(@NonNull SlideDeck updatedAttachment) {
return new Quote(id, author, text, missing, updatedAttachment, mentions);
return new Quote(id, author, text, missing, updatedAttachment, mentions, quoteType);
}
@@ -63,4 +67,8 @@ public class Quote {
public @NonNull SlideDeck getAttachment() {
return attachment;
}
public @NonNull QuoteModel.Type getQuoteType() {
return quoteType;
}
}

View File

@@ -41,6 +41,7 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.mms.QuoteModel;
import org.thoughtcrime.securesms.net.NotPushRegisteredException;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
@@ -303,6 +304,7 @@ public abstract class PushSendJob extends SendJob {
String quoteBody = message.getOutgoingQuote().getText();
RecipientId quoteAuthor = message.getOutgoingQuote().getAuthor();
List<SignalServiceDataMessage.Mention> quoteMentions = getMentionsFor(message.getOutgoingQuote().getMentions());
QuoteModel.Type quoteType = message.getOutgoingQuote().getType();
List<SignalServiceDataMessage.Quote.QuotedAttachment> quoteAttachments = new LinkedList<>();
List<Attachment> filteredAttachments = Stream.of(message.getOutgoingQuote().getAttachments())
.filterNot(a -> MediaUtil.isViewOnceType(a.getContentType()))
@@ -351,7 +353,7 @@ public abstract class PushSendJob extends SendJob {
if (quoteAuthorRecipient.isMaybeRegistered()) {
SignalServiceAddress quoteAddress = RecipientUtil.toSignalServiceAddress(context, quoteAuthorRecipient);
return Optional.of(new SignalServiceDataMessage.Quote(quoteId, quoteAddress, quoteBody, quoteAttachments, quoteMentions));
return Optional.of(new SignalServiceDataMessage.Quote(quoteId, quoteAddress, quoteBody, quoteAttachments, quoteMentions, quoteType.getDataMessageType()));
} else {
return Optional.empty();
}

View File

@@ -1565,7 +1565,7 @@ public final class MessageContentProcessor {
}
parentStoryId = new ParentStoryId.DirectReply(storyMessageId.getId());
quoteModel = new QuoteModel(storyContext.getSentTimestamp(), storyAuthorRecipient, displayText, false, story.getSlideDeck().asAttachments(), Collections.emptyList());
quoteModel = new QuoteModel(storyContext.getSentTimestamp(), storyAuthorRecipient, displayText, false, story.getSlideDeck().asAttachments(), Collections.emptyList(), QuoteModel.Type.NORMAL);
expiresInMillis = TimeUnit.SECONDS.toMillis(message.getExpiresInSeconds());
} else {
warn(content.getTimestamp(), "Story has reactions disabled. Dropping reaction.");
@@ -1656,7 +1656,7 @@ public final class MessageContentProcessor {
displayText = story.getBody();
}
quoteModel = new QuoteModel(storyContext.getSentTimestamp(), storyAuthorRecipient, displayText, false, story.getSlideDeck().asAttachments(), Collections.emptyList());
quoteModel = new QuoteModel(storyContext.getSentTimestamp(), storyAuthorRecipient, displayText, false, story.getSlideDeck().asAttachments(), Collections.emptyList(), QuoteModel.Type.NORMAL);
expiresInMillis = TimeUnit.SECONDS.toMillis(message.getExpiresInSeconds());
} else {
warn(content.getTimestamp(), "Story has replies disabled. Dropping reply.");
@@ -1929,7 +1929,7 @@ public final class MessageContentProcessor {
quoteBody = story.getBody();
}
quoteModel = new QuoteModel(storyContext.getSentTimestamp(), storyAuthorRecipient, quoteBody, false, story.getSlideDeck().asAttachments(), Collections.emptyList());
quoteModel = new QuoteModel(storyContext.getSentTimestamp(), storyAuthorRecipient, quoteBody, false, story.getSlideDeck().asAttachments(), Collections.emptyList(), QuoteModel.Type.NORMAL);
expiresInMillis = TimeUnit.SECONDS.toMillis(message.getExpirationStartTimestamp());
} else {
warn(envelopeTimestamp, "Story has replies disabled. Dropping reply.");
@@ -2722,7 +2722,7 @@ public final class MessageContentProcessor {
}
}
return Optional.of(new QuoteModel(quote.get().getId(), author, message.getBody(), false, attachments, mentions));
return Optional.of(new QuoteModel(quote.get().getId(), author, message.getBody(), false, attachments, mentions, QuoteModel.Type.fromDataMessageType(quote.get().getType())));
} else if (message != null) {
warn("Found the target for the quote, but it's flagged as remotely deleted.");
}
@@ -2730,11 +2730,12 @@ public final class MessageContentProcessor {
warn("Didn't find matching message record...");
return Optional.of(new QuoteModel(quote.get().getId(),
author,
quote.get().getText(),
true,
PointerAttachment.forPointers(quote.get().getAttachments()),
getMentions(quote.get().getMentions())));
author,
quote.get().getText(),
true,
PointerAttachment.forPointers(quote.get().getAttachments()),
getMentions(quote.get().getMentions()),
QuoteModel.Type.fromDataMessageType(quote.get().getType())));
}
private Optional<Attachment> getStickerAttachment(Optional<SignalServiceDataMessage.Sticker> sticker) {

View File

@@ -7,6 +7,7 @@ import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.database.model.Mention;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import java.util.Collections;
import java.util.List;
@@ -19,14 +20,23 @@ public class QuoteModel {
private final boolean missing;
private final List<Attachment> attachments;
private final List<Mention> mentions;
private final Type type;
public QuoteModel(long id, @NonNull RecipientId author, String text, boolean missing, @Nullable List<Attachment> attachments, @Nullable List<Mention> mentions) {
public QuoteModel(long id,
@NonNull RecipientId author,
String text,
boolean missing,
@Nullable List<Attachment> attachments,
@Nullable List<Mention> mentions,
@NonNull Type type)
{
this.id = id;
this.author = author;
this.text = text;
this.missing = missing;
this.attachments = attachments;
this.mentions = mentions != null ? mentions : Collections.emptyList();
this.type = type;
}
public long getId() {
@@ -52,4 +62,49 @@ public class QuoteModel {
public @NonNull List<Mention> getMentions() {
return mentions;
}
public Type getType() {
return type;
}
public enum Type {
NORMAL(0, SignalServiceDataMessage.Quote.Type.NORMAL),
GIFT_BADGE(1, SignalServiceDataMessage.Quote.Type.GIFT_BADGE);
private final int code;
private final SignalServiceDataMessage.Quote.Type dataMessageType;
Type(int code, @NonNull SignalServiceDataMessage.Quote.Type dataMessageType) {
this.code = code;
this.dataMessageType = dataMessageType;
}
public int getCode() {
return code;
}
public @NonNull SignalServiceDataMessage.Quote.Type getDataMessageType() {
return dataMessageType;
}
public static Type fromCode(int code) {
for (final Type value : values()) {
if (value.code == code) {
return value;
}
}
throw new IllegalArgumentException("Invalid code: " + code);
}
public static Type fromDataMessageType(@NonNull SignalServiceDataMessage.Quote.Type dataMessageType) {
for (final Type value : values()) {
if (value.dataMessageType == dataMessageType) {
return value;
}
}
return NORMAL;
}
}
}

View File

@@ -20,6 +20,7 @@ import org.thoughtcrime.securesms.components.emoji.MediaKeyboard
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
import org.thoughtcrime.securesms.database.model.Mention
import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.mms.QuoteModel
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.util.visible
@@ -106,7 +107,8 @@ class StoryReplyComposer @JvmOverloads constructor(
false,
messageRecord.slideDeck,
null,
null
null,
QuoteModel.Type.NORMAL
)
quoteView.visible = true

View File

@@ -55,7 +55,7 @@ class StoryDirectReplyRepository(context: Context) {
StoryType.NONE,
ParentStoryId.DirectReply(storyId),
isReaction,
QuoteModel(message.dateSent, quoteAuthor.id, message.body, false, message.slideDeck.asAttachments(), null),
QuoteModel(message.dateSent, quoteAuthor.id, message.body, false, message.slideDeck.asAttachments(), null, QuoteModel.Type.NORMAL),
emptyList(),
emptyList(),
emptyList(),

View File

@@ -9,6 +9,7 @@ import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge
import org.thoughtcrime.securesms.mms.QuoteModel
import org.thoughtcrime.securesms.mms.TextSlide
import org.thoughtcrime.securesms.stickers.StickerUrl
@@ -127,3 +128,10 @@ fun MessageRecord.isTextOnly(context: Context): Boolean {
!hasGiftBadge()
)
}
/**
* Returns the QuoteType for this record, as if it was being quoted.
*/
fun MessageRecord.getRecordQuoteType(): QuoteModel.Type {
return if (hasGiftBadge()) QuoteModel.Type.GIFT_BADGE else QuoteModel.Type.NORMAL
}