Do not linkify message body if recipient is not message request accepted.

Co-authored-by: Greyson Parrelli <greyson@signal.org>
fork-5.53.8
Alan Evans 2021-02-03 12:45:14 -04:00 zatwierdzone przez Greyson Parrelli
rodzic 213ffdab62
commit ddb04c6ea3
8 zmienionych plików z 67 dodań i 29 usunięć

Wyświetl plik

@ -37,7 +37,8 @@ public interface BindableConversationItem extends Unbindable {
@NonNull Recipient recipients, @NonNull Recipient recipients,
@Nullable String searchQuery, @Nullable String searchQuery,
boolean pulseMention, boolean pulseMention,
boolean hasWallpaper); boolean hasWallpaper,
boolean isMessageRequestAccepted);
ConversationMessage getConversationMessage(); ConversationMessage getConversationMessage();

Wyświetl plik

@ -17,7 +17,6 @@
package org.thoughtcrime.securesms.conversation; package org.thoughtcrime.securesms.conversation;
import android.content.Context; import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -44,6 +43,7 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.thoughtcrime.securesms.util.CachedInflater; import org.thoughtcrime.securesms.util.CachedInflater;
import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration; import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
@ -112,6 +112,7 @@ public class ConversationAdapter
private View footerView; private View footerView;
private PagingController pagingController; private PagingController pagingController;
private boolean hasWallpaper; private boolean hasWallpaper;
private boolean isMessageRequestAccepted;
ConversationAdapter(@NonNull LifecycleOwner lifecycleOwner, ConversationAdapter(@NonNull LifecycleOwner lifecycleOwner,
@NonNull GlideRequests glideRequests, @NonNull GlideRequests glideRequests,
@ -143,6 +144,7 @@ public class ConversationAdapter
this.calendar = Calendar.getInstance(); this.calendar = Calendar.getInstance();
this.digest = getMessageDigestOrThrow(); this.digest = getMessageDigestOrThrow();
this.hasWallpaper = recipient.hasWallpaper(); this.hasWallpaper = recipient.hasWallpaper();
this.isMessageRequestAccepted = true;
setHasStableIds(true); setHasStableIds(true);
} }
@ -254,7 +256,8 @@ public class ConversationAdapter
recipient, recipient,
searchQuery, searchQuery,
conversationMessage == recordToPulse, conversationMessage == recordToPulse,
hasWallpaper); hasWallpaper,
isMessageRequestAccepted);
if (conversationMessage == recordToPulse) { if (conversationMessage == recordToPulse) {
recordToPulse = null; recordToPulse = null;
@ -595,6 +598,13 @@ public class ConversationAdapter
return getItem(position - ((hasFooter() && position == getItemCount() - 1) ? 1 : 0)); return getItem(position - ((hasFooter() && position == getItemCount() - 1) ? 1 : 0));
} }
public void setMessageRequestAccepted(boolean messageRequestAccepted) {
if (this.isMessageRequestAccepted != messageRequestAccepted) {
this.isMessageRequestAccepted = messageRequestAccepted;
notifyDataSetChanged();
}
}
static class ConversationViewHolder extends RecyclerView.ViewHolder { static class ConversationViewHolder extends RecyclerView.ViewHolder {
public ConversationViewHolder(final @NonNull View itemView) { public ConversationViewHolder(final @NonNull View itemView) {
super(itemView); super(itemView);

Wyświetl plik

@ -23,7 +23,6 @@ import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Rect;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
@ -105,6 +104,7 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.longmessage.LongMessageActivity; import org.thoughtcrime.securesms.longmessage.LongMessageActivity;
import org.thoughtcrime.securesms.mediasend.Media; import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.messagedetails.MessageDetailsActivity; import org.thoughtcrime.securesms.messagedetails.MessageDetailsActivity;
import org.thoughtcrime.securesms.messagerequests.MessageRequestState;
import org.thoughtcrime.securesms.messagerequests.MessageRequestViewModel; import org.thoughtcrime.securesms.messagerequests.MessageRequestViewModel;
import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage; import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
@ -426,6 +426,13 @@ public class ConversationFragment extends LoggingFragment {
presentMessageRequestProfileView(requireContext(), recipientInfo, conversationBanner); presentMessageRequestProfileView(requireContext(), recipientInfo, conversationBanner);
presentMessageRequestProfileView(requireContext(), recipientInfo, emptyConversationBanner); presentMessageRequestProfileView(requireContext(), recipientInfo, emptyConversationBanner);
}); });
messageRequestViewModel.getMessageData().observe(getViewLifecycleOwner(), data -> {
ConversationAdapter adapter = getListAdapter();
if (adapter != null) {
adapter.setMessageRequestAccepted(data.getMessageState() == MessageRequestState.NONE);
}
});
} }
private static void presentMessageRequestProfileView(@NonNull Context context, @NonNull MessageRequestViewModel.RecipientInfo recipientInfo, @Nullable ConversationBannerView conversationBanner) { private static void presentMessageRequestProfileView(@NonNull Context context, @NonNull MessageRequestViewModel.RecipientInfo recipientInfo, @Nullable ConversationBannerView conversationBanner) {

Wyświetl plik

@ -259,7 +259,8 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
@NonNull Recipient conversationRecipient, @NonNull Recipient conversationRecipient,
@Nullable String searchQuery, @Nullable String searchQuery,
boolean pulse, boolean pulse,
boolean hasWallpaper) boolean hasWallpaper,
boolean isMessageRequestAccepted)
{ {
if (this.recipient != null) this.recipient.removeForeverObserver(this); if (this.recipient != null) this.recipient.removeForeverObserver(this);
if (this.conversationRecipient != null) this.conversationRecipient.removeForeverObserver(this); if (this.conversationRecipient != null) this.conversationRecipient.removeForeverObserver(this);
@ -280,8 +281,8 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
setGutterSizes(messageRecord, groupThread); setGutterSizes(messageRecord, groupThread);
setMessageShape(messageRecord, previousMessageRecord, nextMessageRecord, groupThread); setMessageShape(messageRecord, previousMessageRecord, nextMessageRecord, groupThread);
setMediaAttributes(messageRecord, previousMessageRecord, nextMessageRecord, conversationRecipient, groupThread, hasWallpaper); setMediaAttributes(messageRecord, previousMessageRecord, nextMessageRecord, groupThread, hasWallpaper, isMessageRequestAccepted);
setBodyText(messageRecord, searchQuery); setBodyText(messageRecord, searchQuery, isMessageRequestAccepted);
setBubbleState(messageRecord, hasWallpaper); setBubbleState(messageRecord, hasWallpaper);
setInteractionState(conversationMessage, pulse); setInteractionState(conversationMessage, pulse);
setStatusIcons(messageRecord, hasWallpaper); setStatusIcons(messageRecord, hasWallpaper);
@ -627,7 +628,8 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
} }
private void setBodyText(@NonNull MessageRecord messageRecord, private void setBodyText(@NonNull MessageRecord messageRecord,
@Nullable String searchQuery) @Nullable String searchQuery,
boolean messageRequestAccepted)
{ {
bodyText.setClickable(false); bodyText.setClickable(false);
bodyText.setFocusable(false); bodyText.setFocusable(false);
@ -649,7 +651,10 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
} else if (isCaptionlessMms(messageRecord)) { } else if (isCaptionlessMms(messageRecord)) {
bodyText.setVisibility(View.GONE); bodyText.setVisibility(View.GONE);
} else { } else {
Spannable styledText = linkifyMessageBody(conversationMessage.getDisplayBody(getContext()), batchSelected.isEmpty()); Spannable styledText = conversationMessage.getDisplayBody(getContext());
if (messageRequestAccepted) {
linkifyMessageBody(styledText, batchSelected.isEmpty());
}
styledText = SearchUtil.getHighlightedSpan(locale, () -> new BackgroundColorSpan(Color.YELLOW), styledText, searchQuery); styledText = SearchUtil.getHighlightedSpan(locale, () -> new BackgroundColorSpan(Color.YELLOW), styledText, searchQuery);
styledText = SearchUtil.getHighlightedSpan(locale, () -> new ForegroundColorSpan(Color.BLACK), styledText, searchQuery); styledText = SearchUtil.getHighlightedSpan(locale, () -> new ForegroundColorSpan(Color.BLACK), styledText, searchQuery);
@ -673,9 +678,9 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
private void setMediaAttributes(@NonNull MessageRecord messageRecord, private void setMediaAttributes(@NonNull MessageRecord messageRecord,
@NonNull Optional<MessageRecord> previousRecord, @NonNull Optional<MessageRecord> previousRecord,
@NonNull Optional<MessageRecord> nextRecord, @NonNull Optional<MessageRecord> nextRecord,
@NonNull Recipient conversationRecipient,
boolean isGroupThread, boolean isGroupThread,
boolean hasWallpaper) boolean hasWallpaper,
boolean messageRequestAccepted)
{ {
boolean showControls = !messageRecord.isFailed(); boolean showControls = !messageRecord.isFailed();
@ -717,7 +722,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ViewUtil.updateLayoutParamsIfNonNull(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParamsIfNonNull(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
footer.setVisibility(GONE); footer.setVisibility(GONE);
} else if (hasLinkPreview(messageRecord)) { } else if (hasLinkPreview(messageRecord) && messageRequestAccepted) {
linkPreviewStub.get().setVisibility(View.VISIBLE); linkPreviewStub.get().setVisibility(View.VISIBLE);
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE);
if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE); if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE);
@ -982,7 +987,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
contactPhoto.setAvatar(glideRequests, recipient, false); contactPhoto.setAvatar(glideRequests, recipient, false);
} }
private SpannableString linkifyMessageBody(@NonNull SpannableString messageBody, private void linkifyMessageBody(@NonNull Spannable messageBody,
boolean shouldLinkifyAllLinks) boolean shouldLinkifyAllLinks)
{ {
int linkPattern = Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS; int linkPattern = Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS;
@ -1007,8 +1012,6 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
for (Annotation annotation : mentionAnnotations) { for (Annotation annotation : mentionAnnotations) {
messageBody.setSpan(new MentionClickableSpan(RecipientId.from(annotation.getValue())), messageBody.getSpanStart(annotation), messageBody.getSpanEnd(annotation), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); messageBody.setSpan(new MentionClickableSpan(RecipientId.from(annotation.getValue())), messageBody.getSpanStart(annotation), messageBody.getSpanEnd(annotation), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} }
return messageBody;
} }
private void setStatusIcons(MessageRecord messageRecord, boolean hasWallpaper) { private void setStatusIcons(MessageRecord messageRecord, boolean hasWallpaper) {

Wyświetl plik

@ -100,7 +100,8 @@ public final class ConversationUpdateItem extends FrameLayout
@NonNull Recipient conversationRecipient, @NonNull Recipient conversationRecipient,
@Nullable String searchQuery, @Nullable String searchQuery,
boolean pulseMention, boolean pulseMention,
boolean hasWallpaper) boolean hasWallpaper,
boolean isMessageRequestAccepted)
{ {
this.batchSelected = batchSelected; this.batchSelected = batchSelected;

Wyświetl plik

@ -19,9 +19,9 @@ import org.thoughtcrime.securesms.database.DatabaseObserver;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.mediasend.Media; import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.mediasend.MediaRepository; import org.thoughtcrime.securesms.mediasend.MediaRepository;
import org.thoughtcrime.securesms.recipients.LiveRecipient;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper; import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
import org.whispersystems.libsignal.util.Pair; import org.whispersystems.libsignal.util.Pair;

Wyświetl plik

@ -88,7 +88,7 @@ final class MessageHeaderViewHolder extends RecyclerView.ViewHolder {
conversationItem = (ConversationItem) receivedStub.inflate(); conversationItem = (ConversationItem) receivedStub.inflate();
} }
} }
conversationItem.bind(lifecycleOwner, conversationMessage, Optional.absent(), Optional.absent(), glideRequests, Locale.getDefault(), new HashSet<>(), conversationMessage.getMessageRecord().getRecipient(), null, false, false); conversationItem.bind(lifecycleOwner, conversationMessage, Optional.absent(), Optional.absent(), glideRequests, Locale.getDefault(), new HashSet<>(), conversationMessage.getMessageRecord().getRecipient(), null, false, false, false);
} }
private void bindErrorState(MessageRecord messageRecord) { private void bindErrorState(MessageRecord messageRecord) {

Wyświetl plik

@ -198,6 +198,22 @@ public final class LiveDataUtil {
return outputLiveData; return outputLiveData;
} }
/**
* Observes a source until the predicate is met. The final value matching the predicate is emitted.
*/
public static @NonNull <A> LiveData<A> until(@NonNull LiveData<A> source, @NonNull Predicate<A> predicate) {
MediatorLiveData<A> mediator = new MediatorLiveData<>();
mediator.addSource(source, newValue -> {
mediator.setValue(newValue);
if (predicate.test(newValue)) {
mediator.removeSource(source);
}
});
return mediator;
}
public interface Combine<A, B, R> { public interface Combine<A, B, R> {
@NonNull R apply(@NonNull A a, @NonNull B b); @NonNull R apply(@NonNull A a, @NonNull B b);
} }