Show name of message sender for groups in conversation list.

This commit is contained in:
Alan Evans 2021-01-27 11:53:31 -04:00 committed by GitHub
parent b5237848e9
commit 23303e5407
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 147 additions and 49 deletions

View file

@ -55,15 +55,15 @@ public final class ConversationUpdateItem extends FrameLayout
private Set<ConversationMessage> batchSelected; private Set<ConversationMessage> batchSelected;
private TextView body; private TextView body;
private MaterialButton actionButton; private MaterialButton actionButton;
private View background; private View background;
private ConversationMessage conversationMessage; private ConversationMessage conversationMessage;
private Recipient conversationRecipient; private Recipient conversationRecipient;
private Optional<MessageRecord> nextMessageRecord; private Optional<MessageRecord> nextMessageRecord;
private MessageRecord messageRecord; private MessageRecord messageRecord;
private LiveData<Spannable> displayBody; private LiveData<SpannableString> displayBody;
private EventListener eventListener; private EventListener eventListener;
private final UpdateObserver updateObserver = new UpdateObserver(); private final UpdateObserver updateObserver = new UpdateObserver();
@ -150,9 +150,9 @@ public final class ConversationUpdateItem extends FrameLayout
} }
} }
UpdateDescription updateDescription = Objects.requireNonNull(messageRecord.getUpdateDisplayBody(getContext())); UpdateDescription updateDescription = Objects.requireNonNull(messageRecord.getUpdateDisplayBody(getContext()));
LiveData<Spannable> liveUpdateMessage = LiveUpdateMessage.fromMessageDescription(getContext(), updateDescription, textColor); LiveData<SpannableString> liveUpdateMessage = LiveUpdateMessage.fromMessageDescription(getContext(), updateDescription, textColor);
LiveData<Spannable> spannableMessage = loading(liveUpdateMessage); LiveData<SpannableString> spannableMessage = loading(liveUpdateMessage);
observeDisplayBody(lifecycleOwner, spannableMessage); observeDisplayBody(lifecycleOwner, spannableMessage);
@ -172,7 +172,7 @@ public final class ConversationUpdateItem extends FrameLayout
} }
/** After a short delay, if the main data hasn't shown yet, then a loading message is displayed. */ /** After a short delay, if the main data hasn't shown yet, then a loading message is displayed. */
private @NonNull LiveData<Spannable> loading(@NonNull LiveData<Spannable> string) { private @NonNull LiveData<SpannableString> loading(@NonNull LiveData<SpannableString> string) {
return LiveDataUtil.until(string, LiveDataUtil.delay(250, new SpannableString(getContext().getString(R.string.ConversationUpdateItem_loading)))); return LiveDataUtil.until(string, LiveDataUtil.delay(250, new SpannableString(getContext().getString(R.string.ConversationUpdateItem_loading))));
} }
@ -208,7 +208,7 @@ public final class ConversationUpdateItem extends FrameLayout
} }
} }
private void observeDisplayBody(@NonNull LifecycleOwner lifecycleOwner, @Nullable LiveData<Spannable> displayBody) { private void observeDisplayBody(@NonNull LifecycleOwner lifecycleOwner, @Nullable LiveData<SpannableString> displayBody) {
if (this.displayBody != displayBody) { if (this.displayBody != displayBody) {
if (this.displayBody != null) { if (this.displayBody != null) {
this.displayBody.removeObserver(updateObserver); this.displayBody.removeObserver(updateObserver);

View file

@ -24,6 +24,7 @@ import android.os.Build;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.text.style.TextAppearanceSpan;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
@ -59,6 +60,7 @@ import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.LiveRecipient; import org.thoughtcrime.securesms.recipients.LiveRecipient;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientForeverObserver; import org.thoughtcrime.securesms.recipients.RecipientForeverObserver;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.Debouncer; import org.thoughtcrime.securesms.util.Debouncer;
import org.thoughtcrime.securesms.util.ExpirationUtil; import org.thoughtcrime.securesms.util.ExpirationUtil;
@ -487,11 +489,47 @@ public final class ConversationListItem extends ConstraintLayout
} else if (extra != null && extra.isRemoteDelete()) { } else if (extra != null && extra.isRemoteDelete()) {
return emphasisAdded(context, context.getString(thread.isOutgoing() ? R.string.ThreadRecord_you_deleted_this_message : R.string.ThreadRecord_this_message_was_deleted), defaultTint); return emphasisAdded(context, context.getString(thread.isOutgoing() ? R.string.ThreadRecord_you_deleted_this_message : R.string.ThreadRecord_this_message_was_deleted), defaultTint);
} else { } else {
return LiveDataUtil.just(new SpannableString(removeNewlines(thread.getBody()))); String body = removeNewlines(thread.getBody());
if (thread.getRecipient().isGroup()) {
RecipientId groupMessageSender = thread.getGroupMessageSender();
if (!groupMessageSender.isUnknown()) {
return describeGroupMessage(context, body, groupMessageSender);
}
}
return LiveDataUtil.just(new SpannableString(body));
} }
} }
} }
private static LiveData<SpannableString> describeGroupMessage(@NonNull Context context,
@NonNull String body,
@NonNull RecipientId groupMessageSender)
{
return whileLoadingShow(body, recipientToStringAsync(groupMessageSender,
r -> createGroupMessageUpdateString(context, body, r)));
}
private static SpannableString createGroupMessageUpdateString(@NonNull Context context,
@NonNull String body,
@NonNull Recipient recipient)
{
String sender = (recipient.isSelf() ? context.getString(R.string.MessageRecord_you)
: recipient.getShortDisplayName(context)) + ": ";
SpannableString spannable = new SpannableString(sender + body);
spannable.setSpan(new TextAppearanceSpan(context, R.style.Signal_Text_Preview_Medium),
0,
sender.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannable;
}
/** After a short delay, if the main data hasn't shown yet, then a loading message is displayed. */
private static @NonNull LiveData<SpannableString> whileLoadingShow(@NonNull String loading, @NonNull LiveData<SpannableString> string) {
return LiveDataUtil.until(string, LiveDataUtil.delay(250, new SpannableString(loading)));
}
private static @NonNull String removeNewlines(@Nullable String text) { private static @NonNull String removeNewlines(@Nullable String text) {
if (text == null) { if (text == null) {
return ""; return "";
@ -512,7 +550,7 @@ public final class ConversationListItem extends ConstraintLayout
return emphasisAdded(LiveUpdateMessage.fromMessageDescription(context, description, defaultTint)); return emphasisAdded(LiveUpdateMessage.fromMessageDescription(context, description, defaultTint));
} }
private static @NonNull LiveData<SpannableString> emphasisAdded(@NonNull LiveData<Spannable> description) { private static @NonNull LiveData<SpannableString> emphasisAdded(@NonNull LiveData<SpannableString> description) {
return Transformations.map(description, sequence -> { return Transformations.map(description, sequence -> {
SpannableString spannable = new SpannableString(sequence); SpannableString spannable = new SpannableString(sequence);
spannable.setSpan(new StyleSpan(Typeface.ITALIC), spannable.setSpan(new StyleSpan(Typeface.ITALIC),

View file

@ -1381,6 +1381,7 @@ public class ThreadDatabase extends Database {
private @Nullable Extra getExtrasFor(MessageRecord record) { private @Nullable Extra getExtrasFor(MessageRecord record) {
boolean messageRequestAccepted = RecipientUtil.isMessageRequestAccepted(context, record.getThreadId()); boolean messageRequestAccepted = RecipientUtil.isMessageRequestAccepted(context, record.getThreadId());
RecipientId threadRecipientId = getRecipientIdForThreadId(record.getThreadId()); RecipientId threadRecipientId = getRecipientIdForThreadId(record.getThreadId());
RecipientId individualRecipient = record.getIndividualRecipient().getId();
if (!messageRequestAccepted && threadRecipientId != null) { if (!messageRequestAccepted && threadRecipientId != null) {
Recipient resolved = Recipient.resolved(threadRecipientId); Recipient resolved = Recipient.resolved(threadRecipientId);
@ -1391,35 +1392,42 @@ public class ThreadDatabase extends Database {
RecipientId from = RecipientId.from(inviteAddState.getAddedOrInvitedBy(), null); RecipientId from = RecipientId.from(inviteAddState.getAddedOrInvitedBy(), null);
if (inviteAddState.isInvited()) { if (inviteAddState.isInvited()) {
Log.i(TAG, "GV2 invite message request from " + from); Log.i(TAG, "GV2 invite message request from " + from);
return Extra.forGroupV2invite(from); return Extra.forGroupV2invite(from, individualRecipient);
} else { } else {
Log.i(TAG, "GV2 message request from " + from); Log.i(TAG, "GV2 message request from " + from);
return Extra.forGroupMessageRequest(from); return Extra.forGroupMessageRequest(from, individualRecipient);
} }
} }
Log.w(TAG, "Falling back to unknown message request state for GV2 message"); Log.w(TAG, "Falling back to unknown message request state for GV2 message");
return Extra.forMessageRequest(); return Extra.forMessageRequest(individualRecipient);
} else { } else {
RecipientId recipientId = DatabaseFactory.getMmsSmsDatabase(context).getGroupAddedBy(record.getThreadId()); RecipientId recipientId = DatabaseFactory.getMmsSmsDatabase(context).getGroupAddedBy(record.getThreadId());
if (recipientId != null) { if (recipientId != null) {
return Extra.forGroupMessageRequest(recipientId); return Extra.forGroupMessageRequest(recipientId, individualRecipient);
} }
} }
} }
return Extra.forMessageRequest(); return Extra.forMessageRequest(individualRecipient);
} }
if (record.isRemoteDelete()) { if (record.isRemoteDelete()) {
return Extra.forRemoteDelete(); return Extra.forRemoteDelete(individualRecipient);
} else if (record.isViewOnce()) { } else if (record.isViewOnce()) {
return Extra.forViewOnce(); return Extra.forViewOnce(individualRecipient);
} else if (record.isMms() && ((MmsMessageRecord) record).getSlideDeck().getStickerSlide() != null) { } else if (record.isMms() && ((MmsMessageRecord) record).getSlideDeck().getStickerSlide() != null) {
StickerSlide slide = Objects.requireNonNull(((MmsMessageRecord) record).getSlideDeck().getStickerSlide()); StickerSlide slide = Objects.requireNonNull(((MmsMessageRecord) record).getSlideDeck().getStickerSlide());
return Extra.forSticker(slide.getEmoji()); return Extra.forSticker(slide.getEmoji(), individualRecipient);
} else if (record.isMms() && ((MmsMessageRecord) record).getSlideDeck().getSlides().size() > 1) { } else if (record.isMms() && ((MmsMessageRecord) record).getSlideDeck().getSlides().size() > 1) {
return Extra.forAlbum(); return Extra.forAlbum(individualRecipient);
}
if (threadRecipientId != null) {
Recipient resolved = Recipient.resolved(threadRecipientId);
if (resolved.isGroup()) {
return Extra.forDefault(individualRecipient);
}
} }
return null; return null;
@ -1590,6 +1598,7 @@ public class ThreadDatabase extends Database {
@JsonProperty private final boolean isMessageRequestAccepted; @JsonProperty private final boolean isMessageRequestAccepted;
@JsonProperty private final boolean isGv2Invite; @JsonProperty private final boolean isGv2Invite;
@JsonProperty private final String groupAddedBy; @JsonProperty private final String groupAddedBy;
@JsonProperty private final String individualRecipientId;
public Extra(@JsonProperty("isRevealable") boolean isRevealable, public Extra(@JsonProperty("isRevealable") boolean isRevealable,
@JsonProperty("isSticker") boolean isSticker, @JsonProperty("isSticker") boolean isSticker,
@ -1598,7 +1607,8 @@ public class ThreadDatabase extends Database {
@JsonProperty("isRemoteDelete") boolean isRemoteDelete, @JsonProperty("isRemoteDelete") boolean isRemoteDelete,
@JsonProperty("isMessageRequestAccepted") boolean isMessageRequestAccepted, @JsonProperty("isMessageRequestAccepted") boolean isMessageRequestAccepted,
@JsonProperty("isGv2Invite") boolean isGv2Invite, @JsonProperty("isGv2Invite") boolean isGv2Invite,
@JsonProperty("groupAddedBy") String groupAddedBy) @JsonProperty("groupAddedBy") String groupAddedBy,
@JsonProperty("individualRecipientId") String individualRecipientId)
{ {
this.isRevealable = isRevealable; this.isRevealable = isRevealable;
this.isSticker = isSticker; this.isSticker = isSticker;
@ -1608,34 +1618,39 @@ public class ThreadDatabase extends Database {
this.isMessageRequestAccepted = isMessageRequestAccepted; this.isMessageRequestAccepted = isMessageRequestAccepted;
this.isGv2Invite = isGv2Invite; this.isGv2Invite = isGv2Invite;
this.groupAddedBy = groupAddedBy; this.groupAddedBy = groupAddedBy;
this.individualRecipientId = individualRecipientId;
} }
public static @NonNull Extra forViewOnce() { public static @NonNull Extra forViewOnce(@NonNull RecipientId individualRecipient) {
return new Extra(true, false, null, false, false, true, false, null); return new Extra(true, false, null, false, false, true, false, null, individualRecipient.serialize());
} }
public static @NonNull Extra forSticker(@Nullable String emoji) { public static @NonNull Extra forSticker(@Nullable String emoji, @NonNull RecipientId individualRecipient) {
return new Extra(false, true, emoji, false, false, true, false, null); return new Extra(false, true, emoji, false, false, true, false, null, individualRecipient.serialize());
} }
public static @NonNull Extra forAlbum() { public static @NonNull Extra forAlbum(@NonNull RecipientId individualRecipient) {
return new Extra(false, false, null, true, false, true, false, null); return new Extra(false, false, null, true, false, true, false, null, individualRecipient.serialize());
} }
public static @NonNull Extra forRemoteDelete() { public static @NonNull Extra forRemoteDelete(@NonNull RecipientId individualRecipient) {
return new Extra(false, false, null, false, true, true, false, null); return new Extra(false, false, null, false, true, true, false, null, individualRecipient.serialize());
} }
public static @NonNull Extra forMessageRequest() { public static @NonNull Extra forMessageRequest(@NonNull RecipientId individualRecipient) {
return new Extra(false, false, null, false, false, false, false, null); return new Extra(false, false, null, false, false, false, false, null, individualRecipient.serialize());
} }
public static @NonNull Extra forGroupMessageRequest(RecipientId recipientId) { public static @NonNull Extra forGroupMessageRequest(@NonNull RecipientId recipientId, @NonNull RecipientId individualRecipient) {
return new Extra(false, false, null, false, false, false, false, recipientId.serialize()); return new Extra(false, false, null, false, false, false, false, recipientId.serialize(), individualRecipient.serialize());
} }
public static @NonNull Extra forGroupV2invite(RecipientId recipientId) { public static @NonNull Extra forGroupV2invite(@NonNull RecipientId recipientId, @NonNull RecipientId individualRecipient) {
return new Extra(false, false, null, false, false, false, true, recipientId.serialize()); return new Extra(false, false, null, false, false, false, true, recipientId.serialize(), individualRecipient.serialize());
}
public static @NonNull Extra forDefault(@NonNull RecipientId individualRecipient) {
return new Extra(false, false, null, false, false, true, false, null, individualRecipient.serialize());
} }
public boolean isViewOnce() { public boolean isViewOnce() {
@ -1669,6 +1684,10 @@ public class ThreadDatabase extends Database {
public @Nullable String getGroupAddedBy() { public @Nullable String getGroupAddedBy() {
return groupAddedBy; return groupAddedBy;
} }
public @Nullable String getIndividualRecipientId() {
return individualRecipientId;
}
} }
enum ReadStatus { enum ReadStatus {

View file

@ -31,7 +31,7 @@ public final class LiveUpdateMessage {
* recreates the string asynchronously when they change. * recreates the string asynchronously when they change.
*/ */
@AnyThread @AnyThread
public static LiveData<Spannable> fromMessageDescription(@NonNull Context context, @NonNull UpdateDescription updateDescription, @ColorInt int defaultTint) { public static LiveData<SpannableString> fromMessageDescription(@NonNull Context context, @NonNull UpdateDescription updateDescription, @ColorInt int defaultTint) {
if (updateDescription.isStringStatic()) { if (updateDescription.isStringStatic()) {
return LiveDataUtil.just(toSpannable(context, updateDescription, updateDescription.getStaticString(), defaultTint)); return LiveDataUtil.just(toSpannable(context, updateDescription, updateDescription.getStaticString(), defaultTint));
} }
@ -49,13 +49,13 @@ public final class LiveUpdateMessage {
/** /**
* Observes a single recipient and recreates the string asynchronously when they change. * Observes a single recipient and recreates the string asynchronously when they change.
*/ */
public static LiveData<Spannable> recipientToStringAsync(@NonNull RecipientId recipientId, public static LiveData<SpannableString> recipientToStringAsync(@NonNull RecipientId recipientId,
@NonNull Function<Recipient, Spannable> createStringInBackground) @NonNull Function<Recipient, SpannableString> createStringInBackground)
{ {
return LiveDataUtil.mapAsync(Recipient.live(recipientId).getLiveData(), createStringInBackground); return LiveDataUtil.mapAsync(Recipient.live(recipientId).getLiveDataResolved(), createStringInBackground);
} }
private static @NonNull Spannable toSpannable(@NonNull Context context, @NonNull UpdateDescription updateDescription, @NonNull String string, @ColorInt int defaultTint) { private static @NonNull SpannableString toSpannable(@NonNull Context context, @NonNull UpdateDescription updateDescription, @NonNull String string, @ColorInt int defaultTint) {
boolean isDarkTheme = ThemeUtil.isDarkTheme(context); boolean isDarkTheme = ThemeUtil.isDarkTheme(context);
int drawableResource = updateDescription.getIconResource(); int drawableResource = updateDescription.getIconResource();
int tint = isDarkTheme ? updateDescription.getDarkTint() : updateDescription.getLightTint(); int tint = isDarkTheme ? updateDescription.getDarkTint() : updateDescription.getLightTint();

View file

@ -40,6 +40,7 @@ public final class ThreadRecord {
private final long threadId; private final long threadId;
private final String body; private final String body;
private final Recipient recipient; private final Recipient recipient;
private final Recipient sender;
private final long type; private final long type;
private final long date; private final long date;
private final long deliveryStatus; private final long deliveryStatus;
@ -61,6 +62,7 @@ public final class ThreadRecord {
this.threadId = builder.threadId; this.threadId = builder.threadId;
this.body = builder.body; this.body = builder.body;
this.recipient = builder.recipient; this.recipient = builder.recipient;
this.sender = builder.sender;
this.date = builder.date; this.date = builder.date;
this.type = builder.type; this.type = builder.type;
this.deliveryStatus = builder.deliveryStatus; this.deliveryStatus = builder.deliveryStatus;
@ -184,6 +186,29 @@ public final class ThreadRecord {
else return null; else return null;
} }
public @NonNull RecipientId getIndividualRecipientId() {
if (extra != null && extra.getIndividualRecipientId() != null) {
return RecipientId.from(extra.getIndividualRecipientId());
} else {
if (getRecipient().isGroup()) {
return RecipientId.UNKNOWN;
} else {
return getRecipient().getId();
}
}
}
public @NonNull RecipientId getGroupMessageSender() {
RecipientId threadRecipientId = getRecipient().getId();
RecipientId individualRecipientId = getIndividualRecipientId();
if (threadRecipientId.equals(individualRecipientId)) {
return Recipient.self().getId();
} else {
return individualRecipientId;
}
}
public boolean isGv2Invite() { public boolean isGv2Invite() {
return extra != null && extra.isGv2Invite(); return extra != null && extra.isGv2Invite();
} }
@ -249,7 +274,8 @@ public final class ThreadRecord {
public static class Builder { public static class Builder {
private long threadId; private long threadId;
private String body; private String body;
private Recipient recipient; private Recipient recipient = Recipient.UNKNOWN;
private Recipient sender = Recipient.UNKNOWN;
private long type; private long type;
private long date; private long date;
private long deliveryStatus; private long deliveryStatus;
@ -281,6 +307,11 @@ public final class ThreadRecord {
return this; return this;
} }
public Builder setSender(@NonNull Recipient sender) {
this.sender = sender;
return this;
}
public Builder setType(long type) { public Builder setType(long type) {
this.type = type; this.type = type;
return this; return this;

View file

@ -34,6 +34,7 @@ public final class LiveRecipient {
private final Context context; private final Context context;
private final MutableLiveData<Recipient> liveData; private final MutableLiveData<Recipient> liveData;
private final LiveData<Recipient> observableLiveData; private final LiveData<Recipient> observableLiveData;
private final LiveData<Recipient> observableLiveDataResolved;
private final Set<RecipientForeverObserver> observers; private final Set<RecipientForeverObserver> observers;
private final Observer<Recipient> foreverObserver; private final Observer<Recipient> foreverObserver;
private final AtomicReference<Recipient> recipient; private final AtomicReference<Recipient> recipient;
@ -53,10 +54,11 @@ public final class LiveRecipient {
o.onRecipientChanged(recipient); o.onRecipientChanged(recipient);
} }
}; };
this.refreshForceNotify = new MutableLiveData<>(System.currentTimeMillis()); this.refreshForceNotify = new MutableLiveData<>(new Object());
this.observableLiveData = LiveDataUtil.combineLatest(LiveDataUtil.distinctUntilChanged(liveData, Recipient::hasSameContent), this.observableLiveData = LiveDataUtil.combineLatest(LiveDataUtil.distinctUntilChanged(liveData, Recipient::hasSameContent),
refreshForceNotify, refreshForceNotify,
(recipient, force) -> recipient); (recipient, force) -> recipient);
this.observableLiveDataResolved = LiveDataUtil.filter(this.observableLiveData, r -> !r.isResolving());
} }
public @NonNull RecipientId getId() { public @NonNull RecipientId getId() {
@ -183,6 +185,10 @@ public final class LiveRecipient {
return observableLiveData; return observableLiveData;
} }
public @NonNull LiveData<Recipient> getLiveDataResolved() {
return observableLiveDataResolved;
}
private @NonNull Recipient fetchAndCacheRecipientFromDisk(@NonNull RecipientId id) { private @NonNull Recipient fetchAndCacheRecipientFromDisk(@NonNull RecipientId id) {
RecipientSettings settings = recipientDatabase.getRecipientSettings(id); RecipientSettings settings = recipientDatabase.getRecipientSettings(id);
RecipientDetails details = settings.getGroupId() != null ? getGroupRecipientDetails(settings) RecipientDetails details = settings.getGroupId() != null ? getGroupRecipientDetails(settings)

View file

@ -285,13 +285,13 @@ public final class ManageRecipientViewModel extends ViewModel {
String profileKeyBase64 = recipient.getProfileKey() != null ? Base64.encodeBytes(recipient.getProfileKey()) : "None"; String profileKeyBase64 = recipient.getProfileKey() != null ? Base64.encodeBytes(recipient.getProfileKey()) : "None";
String profileKeyHex = recipient.getProfileKey() != null ? Hex.toStringCondensed(recipient.getProfileKey()) : "None"; String profileKeyHex = recipient.getProfileKey() != null ? Hex.toStringCondensed(recipient.getProfileKey()) : "None";
return String.format("-- Profile Name --\n%s\n\n" + return String.format("-- Profile Name --\n[%s] [%s]\n\n" +
"-- Profile Sharing --\n%s\n\n" + "-- Profile Sharing --\n%s\n\n" +
"-- Profile Key (Base64) --\n%s\n\n" + "-- Profile Key (Base64) --\n%s\n\n" +
"-- Profile Key (Hex) --\n%s\n\n" + "-- Profile Key (Hex) --\n%s\n\n" +
"-- UUID --\n%s\n\n" + "-- UUID --\n%s\n\n" +
"-- RecipientId --\n%s", "-- RecipientId --\n%s",
recipient.getProfileName().toString(), recipient.getProfileName().getGivenName(), recipient.getProfileName().getFamilyName(),
recipient.isProfileSharing(), recipient.isProfileSharing(),
profileKeyBase64, profileKeyBase64,
profileKeyHex, profileKeyHex,

View file

@ -22,6 +22,10 @@
<item name="android:letterSpacing" tools:ignore="NewApi">0.01</item> <item name="android:letterSpacing" tools:ignore="NewApi">0.01</item>
</style> </style>
<style name="Signal.Text.Preview.Medium">
<item name="android:fontFamily">sans-serif-medium</item>
</style>
<style name="Signal.Text.Caption" parent="Base.TextAppearance.AppCompat.Caption"> <style name="Signal.Text.Caption" parent="Base.TextAppearance.AppCompat.Caption">
<item name="android:textSize">12sp</item> <item name="android:textSize">12sp</item>
<item name="android:lineSpacingExtra">2sp</item> <item name="android:lineSpacingExtra">2sp</item>