Add support for replying to gift badges.

fork-5.53.8
Alex Hart 2022-05-10 10:10:35 -03:00
rodzic 0c1edd6a56
commit 8ca0f4baf4
22 zmienionych plików z 247 dodań i 54 usunięć

Wyświetl plik

@ -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();
}

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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());

Wyświetl plik

@ -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();

Wyświetl plik

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

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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);

Wyświetl plik

@ -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

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -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();
}

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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;
}
}
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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(),

Wyświetl plik

@ -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
}

Wyświetl plik

@ -0,0 +1,21 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="54dp"
android:height="54dp"
android:viewportWidth="54"
android:viewportHeight="54">
<path
android:pathData="M0,0h54v54h-54z"
android:fillColor="#2c6bed"/>
<path
android:pathData="M0,24h54v6h-54z"
android:fillColor="#fff"/>
<path
android:pathData="M24,0h6v54h-6z"
android:fillColor="#fff"/>
<path
android:pathData="M42.511,31.491l-2.634,-1.805c1.097,-0.398 2.01,-0.915 2.445,-1.579 0.335,-0.511 0.4,-1.1 0.183,-1.659 -1.25,-3.227 -2.974,-6.048 -5.124,-8.385l-0.344,-0.374 -0.472,0.17c-3.578,1.286 -6.631,4.836 -8.029,6.674 -0.32,-0.092 -0.681,-0.117 -1.037,-0.117s-0.718,0.025 -1.038,0.116c-1.398,-1.838 -4.45,-5.388 -8.028,-6.673l-0.472,-0.17 -0.344,0.374c-2.149,2.337 -3.873,5.158 -5.123,8.385 -0.217,0.559 -0.151,1.148 0.183,1.659 0.435,0.664 1.349,1.181 2.446,1.579l-2.634,1.805 -0.408,0.279 0.069,0.5 0.997,7.228 0.188,1.362 1.054,-0.843c0.305,-0.244 7.479,-5.981 8.787,-7.116 0.358,-0.311 1.719,-1.516 2.779,-2.799 0.38,0.13 0.879,0.193 1.545,0.193s1.164,-0.062 1.545,-0.193c1.06,1.283 2.42,2.488 2.779,2.799 1.309,1.135 8.482,6.872 8.787,7.116l1.054,0.843 0.188,-1.362 0.997,-7.228 0.069,-0.5 -0.408,-0.279h0Z"
android:fillColor="#2c6bed"/>
<path
android:pathData="M33.263,30.817c1.091,0 3.541,-0.229 5.658,-0.825l3.161,2.167 -0.997,7.228s-7.452,-5.958 -8.763,-7.096c-0.634,-0.55 -1.395,-1.27 -2.073,-2.005 0.698,0.231 1.535,0.44 2.435,0.512 0.168,0.014 0.362,0.02 0.579,0.02h0ZM13.915,39.385s7.452,-5.958 8.763,-7.096c0.634,-0.55 1.395,-1.27 2.073,-2.005 -0.698,0.231 -1.535,0.44 -2.435,0.512 -0.168,0.014 -0.362,0.02 -0.579,0.02 -1.091,0 -3.541,-0.229 -5.658,-0.825l-3.161,2.167 0.997,7.228h0ZM28.756,25.737c-0.038,-0.205 -0.06,-0.522 -1.256,-0.522s-1.218,0.317 -1.256,0.522l-0.476,3.046c-0.048,0.26 0,0.712 1.731,0.712s1.779,-0.452 1.731,-0.712l-0.475,-3.046h0ZM41.787,26.745c-0.89,-2.298 -2.397,-5.338 -4.966,-8.132 -3.317,1.192 -6.225,4.532 -7.603,6.324 0.143,0.164 0.25,0.373 0.3,0.652l0.002,0.01 0.002,0.011 0.474,3.038c0.048,0.274 0.01,0.498 -0.061,0.677 0.734,0.284 1.73,0.586 2.81,0.673 0.149,0.012 0.323,0.018 0.518,0.018 2.684,0 9.354,-1.128 8.524,-3.27h0ZM25.005,28.647l0.474,-3.038 0.005,-0.026 0.002,-0.009c0.048,-0.273 0.154,-0.48 0.295,-0.64 -1.379,-1.792 -4.285,-5.13 -7.601,-6.321 -2.569,2.793 -4.076,5.834 -4.966,8.132 -0.83,2.142 5.84,3.27 8.524,3.27 0.195,0 0.369,-0.006 0.518,-0.018 1.08,-0.087 2.077,-0.389 2.81,-0.673 -0.07,-0.179 -0.109,-0.403 -0.06,-0.677h0Z"
android:fillColor="#fff"/>
</vector>

Wyświetl plik

@ -2107,6 +2107,8 @@
<string name="QuoteView_your_story">You · Story</string>
<!-- Label indicating that the story being replied to no longer exists -->
<string name="QuoteView_no_longer_available">No longer available</string>
<!-- Label for quoted gift -->
<string name="QuoteView__gift">Gift</string>
<!-- conversation_fragment -->
<string name="conversation_fragment__scroll_to_the_bottom_content_description">Scroll to the bottom</string>

Wyświetl plik

@ -107,6 +107,7 @@ object TestMms {
values.putNull(MmsDatabase.QUOTE_BODY)
values.putNull(MmsDatabase.QUOTE_AUTHOR)
values.putNull(MmsDatabase.QUOTE_ATTACHMENT)
values.put(MmsDatabase.QUOTE_TYPE, -1)
values.putNull(MmsDatabase.QUOTE_ID)
values.putNull(MmsDatabase.LINK_PREVIEWS)
values.putNull(MmsDatabase.SHARED_CONTACTS)

Wyświetl plik

@ -846,7 +846,8 @@ public class SignalServiceMessageSender {
DataMessage.Quote.Builder quoteBuilder = DataMessage.Quote.newBuilder()
.setId(message.getQuote().get().getId())
.setText(message.getQuote().get().getText())
.setAuthorUuid(message.getQuote().get().getAuthor().getServiceId().toString());
.setAuthorUuid(message.getQuote().get().getAuthor().getServiceId().toString())
.setType(message.getQuote().get().getType().getProtoType());
if (!message.getQuote().get().getMentions().isEmpty()) {
for (SignalServiceDataMessage.Mention mention : message.getQuote().get().getMentions()) {

Wyświetl plik

@ -1021,7 +1021,8 @@ public final class SignalServiceContent {
address,
content.getQuote().getText(),
attachments,
createMentions(content.getQuote().getBodyRangesList(), content.getQuote().getText(), isGroupV2));
createMentions(content.getQuote().getBodyRangesList(), content.getQuote().getText(), isGroupV2),
SignalServiceDataMessage.Quote.Type.fromProto(content.getQuote().getType()));
} else {
Log.w(TAG, "Quote was missing an author! Returning null.");
return null;

Wyświetl plik

@ -13,6 +13,7 @@ import org.whispersystems.signalservice.api.messages.shared.SharedContact;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.util.OptionalUtil;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
import java.util.LinkedList;
import java.util.List;
@ -456,13 +457,21 @@ public class SignalServiceDataMessage {
private final String text;
private final List<QuotedAttachment> attachments;
private final List<Mention> mentions;
private final Type type;
public Quote(long id, SignalServiceAddress author, String text, List<QuotedAttachment> attachments, List<Mention> mentions) {
public Quote(long id,
SignalServiceAddress author,
String text,
List<QuotedAttachment> attachments,
List<Mention> mentions,
Type type)
{
this.id = id;
this.author = author;
this.text = text;
this.attachments = attachments;
this.mentions = mentions;
this.type = type;
}
public long getId() {
@ -485,6 +494,35 @@ public class SignalServiceDataMessage {
return mentions;
}
public Type getType() {
return type;
}
public enum Type {
NORMAL(SignalServiceProtos.DataMessage.Quote.Type.NORMAL),
GIFT_BADGE(SignalServiceProtos.DataMessage.Quote.Type.GIFT_BADGE);
private final SignalServiceProtos.DataMessage.Quote.Type protoType;
Type(SignalServiceProtos.DataMessage.Quote.Type protoType) {
this.protoType = protoType;
}
public SignalServiceProtos.DataMessage.Quote.Type getProtoType() {
return protoType;
}
public static Type fromProto(SignalServiceProtos.DataMessage.Quote.Type protoType) {
for (final Type value : values()) {
if (value.protoType == protoType) {
return value;
}
}
return NORMAL;
}
}
public static class QuotedAttachment {
private final String contentType;
private final String fileName;

Wyświetl plik

@ -138,6 +138,11 @@ message DataMessage {
}
message Quote {
enum Type {
NORMAL = 0;
GIFT_BADGE = 1;
}
message QuotedAttachment {
optional string contentType = 1;
optional string fileName = 2;
@ -150,6 +155,7 @@ message DataMessage {
optional string text = 3;
repeated QuotedAttachment attachments = 4;
repeated BodyRange bodyRanges = 6;
optional Type type = 7;
}
message Contact {