Add poll icon when quoting a poll.

This commit is contained in:
Michelle Tang
2025-10-16 13:32:33 -04:00
committed by Cody Henthorne
parent 91b70038e6
commit b3f74d37e1
9 changed files with 39 additions and 15 deletions

View File

@@ -1117,6 +1117,7 @@ private fun BackupMessageRecord.toRemoteQuote(exportState: ExportState, attachme
} }
} }
QuoteModel.Type.GIFT_BADGE -> Quote.Type.GIFT_BADGE QuoteModel.Type.GIFT_BADGE -> Quote.Type.GIFT_BADGE
QuoteModel.Type.POLL -> Quote.Type.POLL
} }
val bodyRanges = this.quoteBodyRanges?.toRemoteBodyRanges(dateSent) ?: emptyList() val bodyRanges = this.quoteBodyRanges?.toRemoteBodyRanges(dateSent) ?: emptyList()

View File

@@ -1053,6 +1053,7 @@ class ChatItemArchiveImporter(
Quote.Type.NORMAL -> QuoteModel.Type.NORMAL.code Quote.Type.NORMAL -> QuoteModel.Type.NORMAL.code
Quote.Type.GIFT_BADGE -> QuoteModel.Type.GIFT_BADGE.code Quote.Type.GIFT_BADGE -> QuoteModel.Type.GIFT_BADGE.code
Quote.Type.VIEW_ONCE -> QuoteModel.Type.NORMAL.code Quote.Type.VIEW_ONCE -> QuoteModel.Type.NORMAL.code
Quote.Type.POLL -> QuoteModel.Type.POLL.code
} }
} }

View File

@@ -4,6 +4,7 @@ package org.thoughtcrime.securesms.components;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.text.SpannableStringBuilder;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
@@ -32,6 +33,7 @@ import org.thoughtcrime.securesms.components.quotes.QuoteViewColorTheme;
import org.thoughtcrime.securesms.conversation.MessageStyler; import org.thoughtcrime.securesms.conversation.MessageStyler;
import org.thoughtcrime.securesms.database.model.Mention; import org.thoughtcrime.securesms.database.model.Mention;
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList; import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
import org.thoughtcrime.securesms.fonts.SignalSymbols;
import org.thoughtcrime.securesms.mms.DecryptableUri; import org.thoughtcrime.securesms.mms.DecryptableUri;
import org.thoughtcrime.securesms.mms.QuoteModel; import org.thoughtcrime.securesms.mms.QuoteModel;
import org.thoughtcrime.securesms.mms.Slide; import org.thoughtcrime.securesms.mms.Slide;
@@ -43,6 +45,7 @@ import org.thoughtcrime.securesms.stories.StoryTextPostModel;
import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.Projection; import org.thoughtcrime.securesms.util.Projection;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.views.Stub; import org.thoughtcrime.securesms.util.views.Stub;
import java.io.IOException; import java.io.IOException;
@@ -231,7 +234,14 @@ public class QuoteView extends ConstraintLayout implements RecipientForeverObser
} }
private @Nullable CharSequence resolveBody(@Nullable CharSequence body, @NonNull QuoteModel.Type quoteType) { private @Nullable CharSequence resolveBody(@Nullable CharSequence body, @NonNull QuoteModel.Type quoteType) {
return quoteType == QuoteModel.Type.GIFT_BADGE ? getContext().getString(R.string.QuoteView__donation_for_a_friend) : body; switch (quoteType) {
case GIFT_BADGE:
return getContext().getString(R.string.QuoteView__donation_for_a_friend);
case POLL:
return getContext().getString(R.string.Poll__poll_question, body);
default:
return body;
}
} }
public void setTopCornerSizes(boolean topLeftLarge, boolean topRightLarge) { public void setTopCornerSizes(boolean topLeftLarge, boolean topRightLarge) {
@@ -317,6 +327,14 @@ public class QuoteView extends ConstraintLayout implements RecipientForeverObser
Log.w(TAG, "Could not parse body of text post.", e); Log.w(TAG, "Could not parse body of text post.", e);
bodyView.setText(""); bodyView.setText("");
} }
} else if (quoteType == QuoteModel.Type.POLL) {
CharSequence glyph = SignalSymbols.getSpannedString(getContext(), SignalSymbols.Weight.REGULAR, SignalSymbols.Glyph.POLL, -1);
// TODO(michelle): Update with RTL poll icon
SpannableStringBuilder builder = new SpannableStringBuilder()
.append(glyph)
.append(" ")
.append(body);
bodyView.setText(body == null ? "" : builder);
} else { } else {
bodyView.setText(body == null ? "" : body); bodyView.setText(body == null ? "" : body);
} }

View File

@@ -85,11 +85,9 @@ import org.thoughtcrime.securesms.util.MediaUtil
import org.thoughtcrime.securesms.util.MessageUtil import org.thoughtcrime.securesms.util.MessageUtil
import org.thoughtcrime.securesms.util.SignalLocalMetrics import org.thoughtcrime.securesms.util.SignalLocalMetrics
import org.thoughtcrime.securesms.util.Util import org.thoughtcrime.securesms.util.Util
import org.thoughtcrime.securesms.util.getPoll
import org.thoughtcrime.securesms.util.hasLinkPreview import org.thoughtcrime.securesms.util.hasLinkPreview
import org.thoughtcrime.securesms.util.hasSharedContact import org.thoughtcrime.securesms.util.hasSharedContact
import org.thoughtcrime.securesms.util.hasTextSlide import org.thoughtcrime.securesms.util.hasTextSlide
import org.thoughtcrime.securesms.util.isPoll
import org.thoughtcrime.securesms.util.isViewOnceMessage import org.thoughtcrime.securesms.util.isViewOnceMessage
import org.thoughtcrime.securesms.util.requireTextSlide import org.thoughtcrime.securesms.util.requireTextSlide
import java.io.IOException import java.io.IOException
@@ -562,11 +560,6 @@ class ConversationRepository(
} }
slideDeck to conversationMessage.getDisplayBody(context) slideDeck to conversationMessage.getDisplayBody(context)
} else if (messageRecord.isPoll()) {
val poll = messageRecord.getPoll()!!
val slideDeck = SlideDeck()
slideDeck to SpannableStringBuilder().append(context.getString(R.string.Poll__poll_question, poll.question))
} else { } else {
var slideDeck = if (messageRecord.isMms) { var slideDeck = if (messageRecord.isMms) {
(messageRecord as MmsMessageRecord).slideDeck (messageRecord as MmsMessageRecord).slideDeck

View File

@@ -26,7 +26,8 @@ class QuoteModel(
enum class Type(val code: Int, val dataMessageType: SignalServiceDataMessage.Quote.Type) { enum class Type(val code: Int, val dataMessageType: SignalServiceDataMessage.Quote.Type) {
NORMAL(0, SignalServiceDataMessage.Quote.Type.NORMAL), NORMAL(0, SignalServiceDataMessage.Quote.Type.NORMAL),
GIFT_BADGE(1, SignalServiceDataMessage.Quote.Type.GIFT_BADGE); GIFT_BADGE(1, SignalServiceDataMessage.Quote.Type.GIFT_BADGE),
POLL(2, SignalServiceDataMessage.Quote.Type.POLL);
companion object { companion object {
@JvmStatic @JvmStatic
@@ -50,10 +51,11 @@ class QuoteModel(
} }
fun fromProto(type: DataMessage.Quote.Type?): Type { fun fromProto(type: DataMessage.Quote.Type?): Type {
return if (type == DataMessage.Quote.Type.GIFT_BADGE) { return when (type) {
GIFT_BADGE DataMessage.Quote.Type.NORMAL -> NORMAL
} else { DataMessage.Quote.Type.GIFT_BADGE -> GIFT_BADGE
NORMAL DataMessage.Quote.Type.POLL -> POLL
null -> NORMAL
} }
} }
} }

View File

@@ -164,7 +164,13 @@ fun MessageRecord.isScheduled(): Boolean {
* Returns the QuoteType for this record, as if it was being quoted. * Returns the QuoteType for this record, as if it was being quoted.
*/ */
fun MessageRecord.getRecordQuoteType(): QuoteModel.Type { fun MessageRecord.getRecordQuoteType(): QuoteModel.Type {
return if (hasGiftBadge()) QuoteModel.Type.GIFT_BADGE else QuoteModel.Type.NORMAL return if (hasGiftBadge()) {
QuoteModel.Type.GIFT_BADGE
} else if (hasPoll()) {
QuoteModel.Type.POLL
} else {
QuoteModel.Type.NORMAL
}
} }
fun MessageRecord.isEditMessage(): Boolean { fun MessageRecord.isEditMessage(): Boolean {

View File

@@ -760,6 +760,7 @@ message Quote {
NORMAL = 1; NORMAL = 1;
GIFT_BADGE = 2; GIFT_BADGE = 2;
VIEW_ONCE = 3; VIEW_ONCE = 3;
POLL = 4;
} }
message QuotedAttachment { message QuotedAttachment {

View File

@@ -291,7 +291,8 @@ class SignalServiceDataMessage private constructor(
) { ) {
enum class Type(val protoType: QuoteProto.Type) { enum class Type(val protoType: QuoteProto.Type) {
NORMAL(QuoteProto.Type.NORMAL), NORMAL(QuoteProto.Type.NORMAL),
GIFT_BADGE(QuoteProto.Type.GIFT_BADGE); GIFT_BADGE(QuoteProto.Type.GIFT_BADGE),
POLL(QuoteProto.Type.POLL);
companion object { companion object {
@JvmStatic @JvmStatic

View File

@@ -177,6 +177,7 @@ message DataMessage {
enum Type { enum Type {
NORMAL = 0; NORMAL = 0;
GIFT_BADGE = 1; GIFT_BADGE = 1;
POLL = 2;
} }
message QuotedAttachment { message QuotedAttachment {