mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-14 23:18:43 +00:00
Show member labels in quotes.
This commit is contained in:
committed by
Michelle Tang
parent
e384a37fab
commit
cb05608422
@@ -219,7 +219,7 @@ public class InputPanel extends ConstraintLayout
|
||||
@NonNull SlideDeck attachments,
|
||||
@NonNull QuoteModel.Type quoteType)
|
||||
{
|
||||
this.quoteView.setQuote(requestManager, id, author, body, false, attachments, null, quoteType, true);
|
||||
this.quoteView.setQuote(requestManager, id, author, body, false, attachments, null, quoteType, true, null);
|
||||
if (listener != null) {
|
||||
this.quoteView.setOnClickListener(v -> listener.onQuoteClicked(id, author.getId()));
|
||||
}
|
||||
|
||||
@@ -22,9 +22,11 @@ import com.google.android.material.imageview.ShapeableImageView;
|
||||
import com.google.android.material.shape.CornerFamily;
|
||||
import com.google.android.material.shape.ShapeAppearanceModel;
|
||||
|
||||
import org.signal.core.util.DimensionUnit;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.core.ui.view.Stub;
|
||||
import org.signal.core.util.DimensionUnit;
|
||||
import org.signal.core.util.Util;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.glide.decryptableuri.DecryptableUri;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiImageView;
|
||||
@@ -32,10 +34,11 @@ import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
|
||||
import org.thoughtcrime.securesms.components.mention.MentionAnnotation;
|
||||
import org.thoughtcrime.securesms.components.quotes.QuoteViewColorTheme;
|
||||
import org.thoughtcrime.securesms.conversation.MessageStyler;
|
||||
import org.thoughtcrime.securesms.conversation.v2.items.SenderNameWithLabelView;
|
||||
import org.thoughtcrime.securesms.database.model.Mention;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
|
||||
import org.thoughtcrime.securesms.fonts.SignalSymbols;
|
||||
import org.signal.glide.decryptableuri.DecryptableUri;
|
||||
import org.thoughtcrime.securesms.groups.memberlabel.MemberLabel;
|
||||
import org.thoughtcrime.securesms.mms.QuoteModel;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
@@ -45,7 +48,6 @@ import org.thoughtcrime.securesms.recipients.RecipientForeverObserver;
|
||||
import org.thoughtcrime.securesms.stories.StoryTextPostModel;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.Projection;
|
||||
import org.signal.core.util.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -81,28 +83,29 @@ public class QuoteView extends ConstraintLayout implements RecipientForeverObser
|
||||
}
|
||||
}
|
||||
|
||||
private TextView authorView;
|
||||
private EmojiTextView bodyView;
|
||||
private View quoteBarView;
|
||||
private ShapeableImageView thumbnailView;
|
||||
private Stub<View> attachmentVideoOVerlayStub;
|
||||
private Stub<TextView> attachmentNameViewStub;
|
||||
private Stub<ImageView> dismissStub;
|
||||
private EmojiImageView missingStoryReaction;
|
||||
private EmojiImageView storyReactionEmoji;
|
||||
private SenderNameWithLabelView authorView;
|
||||
private EmojiTextView bodyView;
|
||||
private View quoteBarView;
|
||||
private ShapeableImageView thumbnailView;
|
||||
private Stub<View> attachmentVideoOVerlayStub;
|
||||
private Stub<TextView> attachmentNameViewStub;
|
||||
private Stub<ImageView> dismissStub;
|
||||
private EmojiImageView missingStoryReaction;
|
||||
private EmojiImageView storyReactionEmoji;
|
||||
|
||||
private long id;
|
||||
private LiveRecipient author;
|
||||
private CharSequence body;
|
||||
private TextView mediaDescriptionText;
|
||||
private Stub<TextView> missingLinkTextStub;
|
||||
private SlideDeck attachments;
|
||||
private MessageType messageType;
|
||||
private int largeCornerRadius;
|
||||
private int smallCornerRadius;
|
||||
private CornerMask cornerMask;
|
||||
private QuoteModel.Type quoteType;
|
||||
private boolean isWallpaperEnabled;
|
||||
private long id;
|
||||
private LiveRecipient author;
|
||||
private CharSequence body;
|
||||
private TextView mediaDescriptionText;
|
||||
private Stub<TextView> missingLinkTextStub;
|
||||
private SlideDeck attachments;
|
||||
private MessageType messageType;
|
||||
private int largeCornerRadius;
|
||||
private int smallCornerRadius;
|
||||
private CornerMask cornerMask;
|
||||
private QuoteModel.Type quoteType;
|
||||
private boolean isWallpaperEnabled;
|
||||
@Nullable private MemberLabel memberLabel;
|
||||
|
||||
private int thumbHeight;
|
||||
private int thumbWidth;
|
||||
@@ -181,13 +184,13 @@ public class QuoteView extends ConstraintLayout implements RecipientForeverObser
|
||||
cornerMask.setTopLeftRadius(radius);
|
||||
cornerMask.setTopRightRadius(radius);
|
||||
} else if (isStoryReply()) {
|
||||
thumbWidth = getResources().getDimensionPixelOffset(R.dimen.quote_story_thumb_width);
|
||||
thumbWidth = getResources().getDimensionPixelOffset(R.dimen.quote_story_thumb_width);
|
||||
thumbHeight = getResources().getDimensionPixelOffset(R.dimen.quote_story_thumb_height);
|
||||
}
|
||||
|
||||
ViewGroup.LayoutParams params = thumbnailView.getLayoutParams();
|
||||
params.height = thumbHeight;
|
||||
params.width = thumbWidth;
|
||||
params.width = thumbWidth;
|
||||
|
||||
thumbnailView.setLayoutParams(params);
|
||||
dismissStub.setVisibility(messageType == MessageType.PREVIEW ? View.VISIBLE : View.GONE);
|
||||
@@ -204,7 +207,8 @@ public class QuoteView extends ConstraintLayout implements RecipientForeverObser
|
||||
@NonNull SlideDeck attachments,
|
||||
@Nullable String storyReaction,
|
||||
@NonNull QuoteModel.Type quoteType,
|
||||
boolean composeMode)
|
||||
boolean composeMode,
|
||||
@Nullable MemberLabel memberLabel)
|
||||
{
|
||||
if (this.author != null) this.author.removeForeverObserver(this);
|
||||
|
||||
@@ -213,6 +217,7 @@ public class QuoteView extends ConstraintLayout implements RecipientForeverObser
|
||||
this.body = body;
|
||||
this.attachments = attachments;
|
||||
this.quoteType = quoteType;
|
||||
this.memberLabel = memberLabel;
|
||||
|
||||
this.author.observeForever(this);
|
||||
|
||||
@@ -267,18 +272,25 @@ public class QuoteView extends ConstraintLayout implements RecipientForeverObser
|
||||
public void onRecipientChanged(@NonNull Recipient recipient) {
|
||||
setQuoteAuthor(recipient);
|
||||
}
|
||||
|
||||
public @NonNull Projection.Corners getCorners() {
|
||||
return new Projection.Corners(cornerMask.getRadii());
|
||||
}
|
||||
|
||||
private void setQuoteAuthor(@NonNull Recipient author) {
|
||||
String name;
|
||||
if (isStoryReply()) {
|
||||
authorView.setText(author.isSelf() ? getContext().getString(R.string.QuoteView_your_story)
|
||||
: getContext().getString(R.string.QuoteView_s_story, author.getDisplayName(getContext())));
|
||||
name = author.isSelf() ? getContext().getString(R.string.QuoteView_your_story)
|
||||
: getContext().getString(R.string.QuoteView_s_story, author.getDisplayName(getContext()));
|
||||
} else {
|
||||
authorView.setText(author.isSelf() ? getContext().getString(R.string.QuoteView_you)
|
||||
: author.getDisplayName(getContext()));
|
||||
name = author.isSelf() ? getContext().getString(R.string.QuoteView_you)
|
||||
: author.getDisplayName(getContext());
|
||||
}
|
||||
|
||||
QuoteViewColorTheme colorTheme = getColorTheme();
|
||||
int foregroundColor = colorTheme.getForegroundColor(getContext());
|
||||
authorView.setSender(name, foregroundColor);
|
||||
authorView.setLabel(memberLabel, foregroundColor, colorTheme.getLabelBackgroundColor(getContext()));
|
||||
}
|
||||
|
||||
private boolean isStoryReply() {
|
||||
@@ -327,12 +339,12 @@ public class QuoteView extends ConstraintLayout implements RecipientForeverObser
|
||||
bodyView.setText("");
|
||||
}
|
||||
} else if (quoteType == QuoteModel.Type.POLL) {
|
||||
CharSequence glyph = SignalSymbols.getSpannedString(getContext(), SignalSymbols.Weight.REGULAR, SignalSymbols.Glyph.POLL, -1);
|
||||
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);
|
||||
.append(glyph)
|
||||
.append(" ")
|
||||
.append(body);
|
||||
bodyView.setText(body == null ? "" : builder);
|
||||
} else {
|
||||
bodyView.setText(body == null ? "" : body);
|
||||
@@ -396,10 +408,10 @@ public class QuoteView extends ConstraintLayout implements RecipientForeverObser
|
||||
attachmentNameViewStub.setVisibility(GONE);
|
||||
thumbnailView.setVisibility(VISIBLE);
|
||||
requestManager.load(model)
|
||||
.centerCrop()
|
||||
.override(thumbWidth, thumbHeight)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.into(thumbnailView);
|
||||
.centerCrop()
|
||||
.override(thumbWidth, thumbHeight)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.into(thumbnailView);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -414,10 +426,10 @@ public class QuoteView extends ConstraintLayout implements RecipientForeverObser
|
||||
attachmentNameViewStub.setVisibility(GONE);
|
||||
thumbnailView.setVisibility(VISIBLE);
|
||||
requestManager.load(R.drawable.ic_gift_thumbnail)
|
||||
.centerCrop()
|
||||
.override(thumbWidth, thumbHeight)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.into(thumbnailView);
|
||||
.centerCrop()
|
||||
.override(thumbWidth, thumbHeight)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.into(thumbnailView);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -536,14 +548,14 @@ public class QuoteView extends ConstraintLayout implements RecipientForeverObser
|
||||
}
|
||||
|
||||
private void applyColorTheme() {
|
||||
boolean isOutgoing = messageType != MessageType.INCOMING && messageType != MessageType.STORY_REPLY_INCOMING;
|
||||
boolean isPreview = messageType == MessageType.PREVIEW || messageType == MessageType.STORY_REPLY_PREVIEW;
|
||||
|
||||
QuoteViewColorTheme quoteViewColorTheme = QuoteViewColorTheme.resolveTheme(isOutgoing, isPreview, isWallpaperEnabled);
|
||||
QuoteViewColorTheme quoteViewColorTheme = getColorTheme();
|
||||
|
||||
quoteBarView.setBackgroundColor(quoteViewColorTheme.getBarColor(getContext()));
|
||||
setBackgroundColor(quoteViewColorTheme.getBackgroundColor(getContext()));
|
||||
authorView.setTextColor(quoteViewColorTheme.getForegroundColor(getContext()));
|
||||
authorView.updateColors(
|
||||
quoteViewColorTheme.getForegroundColor(getContext()),
|
||||
quoteViewColorTheme.getLabelBackgroundColor(getContext())
|
||||
);
|
||||
bodyView.setTextColor(quoteViewColorTheme.getForegroundColor(getContext()));
|
||||
|
||||
if (attachmentNameViewStub.resolved()) {
|
||||
@@ -556,4 +568,10 @@ public class QuoteView extends ConstraintLayout implements RecipientForeverObser
|
||||
missingLinkTextStub.get().setBackgroundColor(quoteViewColorTheme.getBackgroundColor(getContext()));
|
||||
}
|
||||
}
|
||||
|
||||
private @NonNull QuoteViewColorTheme getColorTheme() {
|
||||
boolean isOutgoing = messageType != MessageType.INCOMING && messageType != MessageType.STORY_REPLY_INCOMING;
|
||||
boolean isPreview = messageType == MessageType.PREVIEW || messageType == MessageType.STORY_REPLY_PREVIEW;
|
||||
return QuoteViewColorTheme.resolveTheme(isOutgoing, isPreview, isWallpaperEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,46 @@
|
||||
package org.thoughtcrime.securesms.components.quotes
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import org.thoughtcrime.securesms.R
|
||||
|
||||
enum class QuoteViewColorTheme(
|
||||
private val backgroundColorRes: Int,
|
||||
private val barColorRes: Int,
|
||||
private val foregroundColorRes: Int
|
||||
@param:ColorRes private val backgroundColorRes: Int,
|
||||
@param:ColorRes private val barColorRes: Int,
|
||||
@param:ColorRes private val foregroundColorRes: Int,
|
||||
@param:ColorRes private val labelBackgroundColorRes: Int
|
||||
) {
|
||||
|
||||
INCOMING_WALLPAPER(
|
||||
R.color.quote_view_background_incoming_wallpaper,
|
||||
R.color.quote_view_bar_incoming_wallpaper,
|
||||
R.color.quote_view_foreground_incoming_wallpaper
|
||||
R.color.quote_view_foreground_incoming_wallpaper,
|
||||
R.color.quote_view_label_background_incoming_wallpaper
|
||||
),
|
||||
INCOMING_NORMAL(
|
||||
R.color.quote_view_background_incoming_normal,
|
||||
R.color.quote_view_bar_incoming_normal,
|
||||
R.color.quote_view_foreground_incoming_normal
|
||||
R.color.quote_view_foreground_incoming_normal,
|
||||
R.color.quote_view_label_background_incoming_normal
|
||||
),
|
||||
OUTGOING_WALLPAPER(
|
||||
R.color.quote_view_background_outgoing_wallpaper,
|
||||
R.color.quote_view_bar_outgoing_wallpaper,
|
||||
R.color.quote_view_foreground_outgoing_wallpaper
|
||||
R.color.quote_view_foreground_outgoing_wallpaper,
|
||||
R.color.quote_view_label_background_outgoing_wallpaper
|
||||
),
|
||||
OUTGOING_NORMAL(
|
||||
R.color.quote_view_background_outgoing_normal,
|
||||
R.color.quote_view_bar_outgoing_normal,
|
||||
R.color.quote_view_foreground_outgoing_normal
|
||||
R.color.quote_view_foreground_outgoing_normal,
|
||||
R.color.quote_view_label_background_outgoing_normal
|
||||
);
|
||||
|
||||
fun getBackgroundColor(context: Context) = ContextCompat.getColor(context, backgroundColorRes)
|
||||
fun getBarColor(context: Context) = ContextCompat.getColor(context, barColorRes)
|
||||
fun getForegroundColor(context: Context) = ContextCompat.getColor(context, foregroundColorRes)
|
||||
fun getLabelBackgroundColor(context: Context) = ContextCompat.getColor(context, labelBackgroundColorRes)
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
|
||||
@@ -125,7 +125,7 @@ object RecipientPreference {
|
||||
style = MemberLabelPillView.Style(
|
||||
horizontalPadding = 8.dp,
|
||||
verticalPadding = 2.dp,
|
||||
textStyle = { MaterialTheme.typography.bodySmall }
|
||||
textStyle = { MaterialTheme.typography.labelSmall }
|
||||
)
|
||||
setLabel(styledLabel.label, styledLabel.tintColor)
|
||||
visible = true
|
||||
|
||||
@@ -1725,7 +1725,8 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||
quote.getAttachment(),
|
||||
isStoryReaction(current) ? current.getBody() : null,
|
||||
quote.getQuoteType(),
|
||||
false);
|
||||
false,
|
||||
conversationMessage.getQuoteMemberLabel());
|
||||
|
||||
quoteView.setWallpaperEnabled(hasWallpaper);
|
||||
quoteView.setVisibility(View.VISIBLE);
|
||||
|
||||
@@ -50,6 +50,7 @@ public class ConversationMessage {
|
||||
@Nullable private final MessageRecord originalMessage;
|
||||
@NonNull private final ComputedProperties computedProperties;
|
||||
@Nullable private final MemberLabel memberLabel;
|
||||
@Nullable private final MemberLabel quoteMemberLabel;
|
||||
|
||||
private ConversationMessage(@NonNull MessageRecord messageRecord,
|
||||
@Nullable CharSequence body,
|
||||
@@ -59,7 +60,8 @@ public class ConversationMessage {
|
||||
@NonNull Recipient threadRecipient,
|
||||
@Nullable MessageRecord originalMessage,
|
||||
@NonNull ComputedProperties computedProperties,
|
||||
@Nullable MemberLabel memberLabel)
|
||||
@Nullable MemberLabel memberLabel,
|
||||
@Nullable MemberLabel quoteMemberLabel)
|
||||
{
|
||||
this.messageRecord = messageRecord;
|
||||
this.hasBeenQuoted = hasBeenQuoted;
|
||||
@@ -69,6 +71,7 @@ public class ConversationMessage {
|
||||
this.originalMessage = originalMessage;
|
||||
this.computedProperties = computedProperties;
|
||||
this.memberLabel = memberLabel;
|
||||
this.quoteMemberLabel = quoteMemberLabel;
|
||||
|
||||
if (body != null) {
|
||||
this.body = SpannableString.valueOf(body);
|
||||
@@ -109,6 +112,10 @@ public class ConversationMessage {
|
||||
return memberLabel;
|
||||
}
|
||||
|
||||
public @Nullable MemberLabel getQuoteMemberLabel() {
|
||||
return quoteMemberLabel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@@ -242,8 +249,9 @@ public class ConversationMessage {
|
||||
}
|
||||
}
|
||||
|
||||
FormattedDate formattedDate = getFormattedDate(context, messageRecord);
|
||||
MemberLabel memberLabel = getMemberLabel(messageRecord, threadRecipient);
|
||||
FormattedDate formattedDate = getFormattedDate(context, messageRecord);
|
||||
MemberLabel memberLabel = getMemberLabel(messageRecord, threadRecipient);
|
||||
MemberLabel quoteMemberLabel = getQuoteMemberLabel(messageRecord, threadRecipient);
|
||||
|
||||
return new ConversationMessage(messageRecord,
|
||||
styledAndMentionBody != null ? styledAndMentionBody : mentionsUpdate != null ? mentionsUpdate.getBody() : body,
|
||||
@@ -253,7 +261,8 @@ public class ConversationMessage {
|
||||
threadRecipient,
|
||||
originalMessage,
|
||||
new ComputedProperties(formattedDate),
|
||||
memberLabel);
|
||||
memberLabel,
|
||||
quoteMemberLabel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,5 +307,15 @@ public class ConversationMessage {
|
||||
}
|
||||
return MemberLabelRepository.getInstance().getLabelJava(threadRecipient.requireGroupId().requireV2(), messageRecord.getFromRecipient());
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private static @Nullable MemberLabel getQuoteMemberLabel(@NonNull MessageRecord messageRecord, @NonNull Recipient threadRecipient) {
|
||||
if (!threadRecipient.isPushV2Group() || !(messageRecord instanceof final MmsMessageRecord mmsMessage) || mmsMessage.getQuote() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Recipient quoteAuthor = Recipient.resolved(mmsMessage.getQuote().getAuthor());
|
||||
return MemberLabelRepository.getInstance().getLabelJava(threadRecipient.requireGroupId().requireV2(), quoteAuthor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@ class SenderNameWithLabelView : AbstractComposeView {
|
||||
|
||||
private var senderName: String by mutableStateOf("")
|
||||
private var senderColor: Color by mutableStateOf(Color.Unspecified)
|
||||
private var labelTextColor: Color by mutableStateOf(Color.Unspecified)
|
||||
private var labelBackgroundColor: Color by mutableStateOf(Color.Unspecified)
|
||||
|
||||
private var memberLabel: MemberLabel? by mutableStateOf(null)
|
||||
|
||||
fun setSender(name: String, @ColorInt tintColor: Int) {
|
||||
@@ -39,16 +42,49 @@ class SenderNameWithLabelView : AbstractComposeView {
|
||||
senderColor = Color(tintColor)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the label with colors derived from the sender name tint color.
|
||||
*/
|
||||
fun setLabel(label: MemberLabel?) {
|
||||
memberLabel = label
|
||||
labelTextColor = Color.Unspecified
|
||||
labelBackgroundColor = Color.Unspecified
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the label with explicit text and background colors.
|
||||
*/
|
||||
fun setLabel(label: MemberLabel?, @ColorInt textColor: Int, @ColorInt backgroundColor: Int) {
|
||||
memberLabel = label
|
||||
labelTextColor = Color(textColor)
|
||||
labelBackgroundColor = Color(backgroundColor)
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to update the colors in response to theme changes (e.g., wallpaper enabled/disabled).
|
||||
*/
|
||||
fun updateColors(@ColorInt foregroundColor: Int, @ColorInt labelBackgroundColor: Int) {
|
||||
senderColor = Color(foregroundColor)
|
||||
labelTextColor = Color(foregroundColor)
|
||||
this.labelBackgroundColor = Color(labelBackgroundColor)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun Content() {
|
||||
SenderNameWithLabel(
|
||||
senderName = senderName,
|
||||
senderColor = senderColor,
|
||||
label = memberLabel
|
||||
)
|
||||
if (labelTextColor != Color.Unspecified || labelBackgroundColor != Color.Unspecified) {
|
||||
SenderNameWithLabel(
|
||||
senderName = senderName,
|
||||
senderColor = senderColor,
|
||||
memberLabel = memberLabel,
|
||||
labelTextColor = labelTextColor,
|
||||
labelBackgroundColor = labelBackgroundColor
|
||||
)
|
||||
} else {
|
||||
SenderNameWithLabel(
|
||||
senderName = senderName,
|
||||
senderColor = senderColor,
|
||||
memberLabel = memberLabel
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,8 @@ class V2ConversationItemMediaViewHolder<Model : MappingModel<Model>>(
|
||||
quote.attachment,
|
||||
if (conversationMessage.messageRecord.isStoryReaction()) conversationMessage.messageRecord.body else null,
|
||||
quote.quoteType,
|
||||
false
|
||||
false,
|
||||
conversationMessage.quoteMemberLabel
|
||||
)
|
||||
|
||||
quoteView.setMessageType(
|
||||
|
||||
@@ -25,6 +25,9 @@ import androidx.compose.ui.unit.dp
|
||||
import org.signal.core.ui.compose.DayNightPreviews
|
||||
import org.signal.core.ui.compose.Previews
|
||||
|
||||
private val defaultModifier = Modifier.padding(horizontal = 12.dp, vertical = 2.dp)
|
||||
private val defaultTextStyle: @Composable () -> TextStyle = { MaterialTheme.typography.bodyLarge }
|
||||
|
||||
/**
|
||||
* Displays member label text with an optional emoji.
|
||||
*/
|
||||
@@ -33,8 +36,8 @@ fun MemberLabelPill(
|
||||
emoji: String?,
|
||||
text: String,
|
||||
tintColor: Color,
|
||||
modifier: Modifier = Modifier.padding(horizontal = 12.dp, vertical = 2.dp),
|
||||
textStyle: TextStyle = MaterialTheme.typography.bodyLarge
|
||||
modifier: Modifier = defaultModifier,
|
||||
textStyle: TextStyle = defaultTextStyle()
|
||||
) {
|
||||
val isDark = isSystemInDarkTheme()
|
||||
val backgroundColor = tintColor.copy(alpha = if (isDark) 0.32f else 0.10f)
|
||||
@@ -45,6 +48,28 @@ fun MemberLabelPill(
|
||||
Color.Black.copy(alpha = 0.30f).compositeOver(tintColor)
|
||||
}
|
||||
|
||||
MemberLabelPill(
|
||||
emoji = emoji,
|
||||
text = text,
|
||||
textColor = textColor,
|
||||
backgroundColor = backgroundColor,
|
||||
modifier = modifier,
|
||||
textStyle = textStyle
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays member label text with an optional emoji.
|
||||
*/
|
||||
@Composable
|
||||
fun MemberLabelPill(
|
||||
emoji: String?,
|
||||
text: String,
|
||||
textColor: Color,
|
||||
backgroundColor: Color,
|
||||
modifier: Modifier = defaultModifier,
|
||||
textStyle: TextStyle = defaultTextStyle()
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.background(
|
||||
|
||||
@@ -17,22 +17,83 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.signal.core.ui.compose.DayNightPreviews
|
||||
import org.signal.core.ui.compose.Previews
|
||||
|
||||
private val defaultLabelModifier = Modifier.padding(horizontal = 6.dp, vertical = 2.dp)
|
||||
private val defaultLabelTextStyle: @Composable () -> TextStyle = { MaterialTheme.typography.bodySmall }
|
||||
|
||||
/**
|
||||
* Displays a sender name with an optional member label pill.
|
||||
* Displays a sender name with an optional member label pill with label colors derived from [senderColor].
|
||||
*/
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun SenderNameWithLabel(
|
||||
senderName: String,
|
||||
senderColor: Color,
|
||||
label: MemberLabel?,
|
||||
memberLabel: MemberLabel?,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
SenderNameWithLabel(
|
||||
senderName = senderName,
|
||||
senderColor = senderColor,
|
||||
memberLabel = memberLabel,
|
||||
modifier = modifier,
|
||||
labelSlot = { label ->
|
||||
MemberLabelPill(
|
||||
emoji = label.emoji,
|
||||
text = label.text,
|
||||
tintColor = senderColor,
|
||||
modifier = defaultLabelModifier,
|
||||
textStyle = defaultLabelTextStyle()
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a sender name with an optional member label pill with explicit label colors.
|
||||
*/
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun SenderNameWithLabel(
|
||||
senderName: String,
|
||||
senderColor: Color,
|
||||
memberLabel: MemberLabel?,
|
||||
labelTextColor: Color,
|
||||
labelBackgroundColor: Color,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
SenderNameWithLabel(
|
||||
senderName = senderName,
|
||||
senderColor = senderColor,
|
||||
memberLabel = memberLabel,
|
||||
modifier = modifier,
|
||||
labelSlot = { label ->
|
||||
MemberLabelPill(
|
||||
emoji = label.emoji,
|
||||
text = label.text,
|
||||
textColor = labelTextColor,
|
||||
backgroundColor = labelBackgroundColor,
|
||||
modifier = defaultLabelModifier,
|
||||
textStyle = defaultLabelTextStyle()
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
private fun SenderNameWithLabel(
|
||||
senderName: String,
|
||||
senderColor: Color,
|
||||
memberLabel: MemberLabel?,
|
||||
modifier: Modifier = Modifier,
|
||||
labelSlot: @Composable (MemberLabel) -> Unit
|
||||
) {
|
||||
FlowRow(
|
||||
modifier = modifier,
|
||||
@@ -49,14 +110,8 @@ fun SenderNameWithLabel(
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
|
||||
if (label != null) {
|
||||
MemberLabelPill(
|
||||
emoji = label.emoji,
|
||||
text = label.text,
|
||||
tintColor = senderColor,
|
||||
textStyle = MaterialTheme.typography.labelSmall,
|
||||
modifier = Modifier.padding(horizontal = 6.dp, vertical = 2.dp)
|
||||
)
|
||||
if (memberLabel != null) {
|
||||
labelSlot(memberLabel)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,7 +123,7 @@ private fun SenderNameWithLabelPreview() = Previews.Preview {
|
||||
SenderNameWithLabel(
|
||||
senderName = "Foo Bar",
|
||||
senderColor = Color(0xFF7C4DFF),
|
||||
label = MemberLabel(emoji = "\uD83D\uDC36", text = "Vet Coordinator")
|
||||
memberLabel = MemberLabel(emoji = "\uD83D\uDC36", text = "Vet Coordinator")
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -80,7 +135,7 @@ private fun SenderNameWithLabelLongLabelPreview() = Previews.Preview {
|
||||
SenderNameWithLabel(
|
||||
senderName = "Foo Bar",
|
||||
senderColor = Color(0xFF7C4DFF),
|
||||
label = MemberLabel(emoji = "🧠", text = "Zero-Knowledge Know-It-All")
|
||||
memberLabel = MemberLabel(emoji = "🧠", text = "Zero-Knowledge Know-It-It-All")
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -92,7 +147,7 @@ private fun SenderNameWithLabelLongNamePreview() = Previews.Preview {
|
||||
SenderNameWithLabel(
|
||||
senderName = "Cassandra NullPointer-Exception",
|
||||
senderColor = Color(0xFF7C4DFF),
|
||||
label = MemberLabel(emoji = "🧠", text = "Vet Coordinator")
|
||||
memberLabel = MemberLabel(emoji = "🧠", text = "Vet Coordinator")
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -104,7 +159,21 @@ private fun SenderNameWithLabelNoLabelPreview() = Previews.Preview {
|
||||
SenderNameWithLabel(
|
||||
senderName = "Sam",
|
||||
senderColor = Color(0xFF4CAF50),
|
||||
label = null
|
||||
memberLabel = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
private fun SenderNameWithLabelExplicitColorsPreview() = Previews.Preview {
|
||||
Box(modifier = Modifier.width(200.dp)) {
|
||||
SenderNameWithLabel(
|
||||
senderName = "Foo Bar",
|
||||
senderColor = MaterialTheme.colorScheme.onSurface,
|
||||
memberLabel = MemberLabel(emoji = "\uD83D\uDC36", text = "Vet Coordinator"),
|
||||
labelTextColor = MaterialTheme.colorScheme.onSurface,
|
||||
labelBackgroundColor = MaterialTheme.colorScheme.surfaceVariant
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,17 +19,14 @@
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@color/signal_colorPrimary" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
<org.thoughtcrime.securesms.conversation.v2.items.SenderNameWithLabelView
|
||||
android:id="@+id/quote_author"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/Signal.Text.LabelLarge"
|
||||
android:textColor="@color/core_black"
|
||||
android:layout_marginBottom="1dp"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/quote_attachment_name_stub"
|
||||
app:layout_constraintEnd_toStartOf="@id/quote_missing_story_reaction_emoji"
|
||||
@@ -37,8 +34,7 @@
|
||||
app:layout_constraintStart_toEndOf="@id/quote_bar"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Peter Parker" />
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/quote_attachment_name_stub"
|
||||
|
||||
@@ -161,16 +161,20 @@
|
||||
|
||||
<color name="quote_view_background_incoming_wallpaper">@color/signal_colorTransparent2</color>
|
||||
<color name="quote_view_bar_incoming_wallpaper">@color/signal_colorNeutralInverse</color>
|
||||
<color name="quote_view_foreground_incoming_wallpaper">@color/signal_colorNeutralInverse</color>
|
||||
<color name="quote_view_foreground_incoming_wallpaper">@color/signal_colorOnSurface</color>
|
||||
<color name="quote_view_background_outgoing_wallpaper">@color/signal_colorTransparent4</color>
|
||||
<color name="quote_view_bar_outgoing_wallpaper">@color/signal_colorNeutralInverse</color>
|
||||
<color name="quote_view_foreground_outgoing_wallpaper">@color/signal_colorNeutral</color>
|
||||
<color name="quote_view_foreground_outgoing_wallpaper">@color/signal_colorOnSurfaceInverse</color>
|
||||
<color name="quote_view_background_incoming_normal">@color/signal_colorTransparent3</color>
|
||||
<color name="quote_view_bar_incoming_normal">@color/signal_colorOnCustom</color>
|
||||
<color name="quote_view_foreground_incoming_normal">@color/signal_colorOnSurface</color>
|
||||
<color name="quote_view_background_outgoing_normal">@color/signal_colorTransparent4</color>
|
||||
<color name="quote_view_bar_outgoing_normal">@color/signal_colorOnCustom</color>
|
||||
<color name="quote_view_foreground_outgoing_normal">@color/signal_light_colorOnSurface</color>
|
||||
<color name="quote_view_foreground_outgoing_normal">@color/signal_colorOnSurfaceInverse</color>
|
||||
<color name="quote_view_label_background_incoming_normal">@color/transparent_white_20</color>
|
||||
<color name="quote_view_label_background_incoming_wallpaper">@color/transparent_white_20</color>
|
||||
<color name="quote_view_label_background_outgoing_normal">@color/transparent_white_20</color>
|
||||
<color name="quote_view_label_background_outgoing_wallpaper">@color/transparent_white_20</color>
|
||||
|
||||
<color name="voice_note_player_view_background">@color/signal_colorSurface1</color>
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
<color name="transparent_white_20">#33ffffff</color>
|
||||
<color name="transparent_white_25">#40ffffff</color>
|
||||
<color name="transparent_white_30">#4Dffffff</color>
|
||||
<color name="transparent_white_36">#5cffffff</color>
|
||||
<color name="transparent_white_40">#66ffffff</color>
|
||||
<color name="transparent_white_60">#99ffffff</color>
|
||||
<color name="transparent_white_70">#b2ffffff</color>
|
||||
|
||||
@@ -178,6 +178,10 @@
|
||||
<color name="quote_view_background_outgoing_normal">@color/signal_colorTransparent4</color>
|
||||
<color name="quote_view_bar_outgoing_normal">@color/signal_colorOnCustom</color>
|
||||
<color name="quote_view_foreground_outgoing_normal">@color/signal_colorOnSurface</color>
|
||||
<color name="quote_view_label_background_incoming_normal">@color/signal_colorOnSurface_8</color>
|
||||
<color name="quote_view_label_background_incoming_wallpaper">@color/transparent_white_80</color>
|
||||
<color name="quote_view_label_background_outgoing_normal">@color/transparent_white_36</color>
|
||||
<color name="quote_view_label_background_outgoing_wallpaper">@color/transparent_white_36</color>
|
||||
|
||||
<color name="react_with_any_background">@color/signal_colorSurface1</color>
|
||||
<color name="react_with_any_search_background">@color/signal_colorSurfaceVariant</color>
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
<color name="signal_colorNeutralVariantInverse">@color/signal_dark_colorNeutralVariantInverse</color>
|
||||
|
||||
<!-- Inverses -->
|
||||
<color name="signal_colorOnSurfaceInverse">@color/signal_light_colorOnSurface</color>
|
||||
<color name="signal_colorErrorInverse">@color/signal_light_colorError</color>
|
||||
<color name="signal_colorErrorContainerInverse">@color/signal_light_colorErrorContainer</color>
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
<color name="signal_colorNeutralVariantInverse">@color/signal_light_colorNeutralVariantInverse</color>
|
||||
|
||||
<!-- Inverses -->
|
||||
<color name="signal_colorOnSurfaceInverse">@color/signal_dark_colorOnSurface</color>
|
||||
<color name="signal_colorErrorInverse">@color/signal_dark_colorError</color>
|
||||
<color name="signal_colorErrorContainerInverse">@color/signal_dark_colorErrorContainer</color>
|
||||
|
||||
@@ -53,6 +54,7 @@
|
||||
<color name="signal_colorSurface_60">#99FBFCFF</color>
|
||||
<color name="signal_colorSurfaceVariant_38">#61E7EBF3</color>
|
||||
<color name="signal_colorSurfaceVariant_64">#A3E7EBF3</color>
|
||||
<color name="signal_colorOnSurface_8">#141B1B1D</color>
|
||||
<color name="signal_colorOnSurface_12">#1F1B1B1D</color>
|
||||
<color name="signal_colorOnSurface_50">#801B1B1D</color>
|
||||
<color name="signal_colorOnSurfaceVariant_60">#99545863</color>
|
||||
|
||||
Reference in New Issue
Block a user