diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/FromTextView.java b/app/src/main/java/org/thoughtcrime/securesms/components/FromTextView.java index 138dda05e1..6504c2eee5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/FromTextView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/FromTextView.java @@ -9,7 +9,6 @@ import androidx.annotation.DrawableRes; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; -import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.components.emoji.SimpleEmojiTextView; import org.thoughtcrime.securesms.recipients.Recipient; @@ -20,8 +19,6 @@ import org.thoughtcrime.securesms.util.ViewUtil; public class FromTextView extends SimpleEmojiTextView { - private static final String TAG = Log.tag(FromTextView.class); - public FromTextView(Context context) { super(context); } @@ -31,22 +28,18 @@ public class FromTextView extends SimpleEmojiTextView { } public void setText(Recipient recipient) { - setText(recipient, true); + setText(recipient, null); } - public void setText(Recipient recipient, boolean read) { - setText(recipient, read, null); + public void setText(Recipient recipient, @Nullable CharSequence suffix) { + setText(recipient, recipient.getDisplayName(getContext()), suffix); } - public void setText(Recipient recipient, boolean read, @Nullable String suffix) { - setText(recipient, recipient.getDisplayName(getContext()), read, suffix); + public void setText(Recipient recipient, @Nullable CharSequence fromString, @Nullable CharSequence suffix) { + setText(recipient, fromString, suffix, true); } - public void setText(Recipient recipient, @Nullable CharSequence fromString, boolean read, @Nullable String suffix) { - setText(recipient, fromString, read, suffix, true); - } - - public void setText(Recipient recipient, @Nullable CharSequence fromString, boolean read, @Nullable String suffix, boolean asThread) { + public void setText(Recipient recipient, @Nullable CharSequence fromString, @Nullable CharSequence suffix, boolean asThread) { SpannableStringBuilder builder = new SpannableStringBuilder(); if (asThread && recipient.isSelf()) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/BioTextPreference.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/BioTextPreference.kt index 324cd53f75..4a1d42dc81 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/BioTextPreference.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/BioTextPreference.kt @@ -2,11 +2,11 @@ package org.thoughtcrime.securesms.components.settings.conversation.preferences import android.content.ClipData import android.content.Context -import android.graphics.drawable.InsetDrawable import android.text.SpannableStringBuilder import android.view.View import android.widget.TextView import android.widget.Toast +import androidx.core.content.ContextCompat import org.signal.core.util.dp import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.components.settings.PreferenceModel @@ -53,17 +53,28 @@ object BioTextPreference { } return SpannableStringBuilder(name).apply { + var appendedToName = false if (recipient.showVerified()) { SpanUtil.appendCenteredImageSpan(this, ContextUtil.requireDrawable(context, R.drawable.ic_official_28), 28, 28) + appendedToName = true + } else if (recipient.isSystemContact) { + val drawable = ContextUtil.requireDrawable(context, R.drawable.symbol_person_circle_24).apply { + setTint(ContextCompat.getColor(context, R.color.signal_colorOnSurface)) + } + SpanUtil.appendCenteredImageSpan(this, drawable, 24, 24) + appendedToName = true } if (recipient.isIndividual && !recipient.isSelf) { - val drawable = ContextUtil.requireDrawable(context, R.drawable.symbol_chevron_right_24_color_on_secondary_container) - drawable.setBounds(0, 0, 24.dp, 24.dp) + val drawable = ContextUtil.requireDrawable(context, R.drawable.symbol_chevron_right_24).apply { + setBounds(0, 0, 24.dp, 24.dp) + setTint(ContextCompat.getColor(context, R.color.signal_colorOutline)) + } - val insetDrawable = InsetDrawable(drawable, 0, 0, 0, 4.dp) - - SpanUtil.appendBottomImageSpan(this, insetDrawable, 24, 28) + if (!appendedToName) { + append(" ") + } + append(SpanUtil.buildCenteredImageSpan(drawable)) } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/RecipientPreference.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/RecipientPreference.kt index 0bfe4c9525..eeaa57e040 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/RecipientPreference.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/preferences/RecipientPreference.kt @@ -1,12 +1,16 @@ package org.thoughtcrime.securesms.components.settings.conversation.preferences +import android.text.SpannableStringBuilder import android.view.View import android.widget.TextView +import androidx.core.content.ContextCompat import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.badges.BadgeImageView import org.thoughtcrime.securesms.components.AvatarImageView import org.thoughtcrime.securesms.components.settings.PreferenceModel import org.thoughtcrime.securesms.recipients.Recipient +import org.thoughtcrime.securesms.util.ContextUtil +import org.thoughtcrime.securesms.util.SpanUtil import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter import org.thoughtcrime.securesms.util.adapter.mapping.MappingViewHolder @@ -56,7 +60,16 @@ object RecipientPreference { name.text = if (model.recipient.isSelf) { context.getString(R.string.Recipient_you) } else { - model.recipient.getDisplayName(context) + if (model.recipient.isSystemContact) { + SpannableStringBuilder(model.recipient.getDisplayName(context)).apply { + val drawable = ContextUtil.requireDrawable(context, R.drawable.symbol_person_circle_24).apply { + setTint(ContextCompat.getColor(context, R.color.signal_colorOnSurface)) + } + SpanUtil.appendCenteredImageSpan(this, drawable, 16, 16) + } + } else { + model.recipient.getDisplayName(context) + } } val aboutText = model.recipient.combinedAboutAndEmoji diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/paged/ContactSearchAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/contacts/paged/ContactSearchAdapter.kt index a8d2118483..3e39b3a0e4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/paged/ContactSearchAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/contacts/paged/ContactSearchAdapter.kt @@ -1,11 +1,13 @@ package org.thoughtcrime.securesms.contacts.paged import android.content.Context +import android.text.SpannableStringBuilder import android.view.View import android.view.ViewGroup import android.widget.CheckBox import android.widget.TextView import androidx.appcompat.widget.AppCompatImageView +import androidx.core.content.ContextCompat import com.google.android.material.button.MaterialButton import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Observable @@ -28,6 +30,8 @@ import org.thoughtcrime.securesms.database.model.DistributionListPrivacyMode import org.thoughtcrime.securesms.database.model.StoryViewState import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.recipients.Recipient +import org.thoughtcrime.securesms.util.ContextUtil +import org.thoughtcrime.securesms.util.SpanUtil import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel @@ -500,7 +504,19 @@ open class ContactSearchAdapter( return } - name.setText(getRecipient(model)) + val recipient = getRecipient(model) + val suffix: CharSequence? = if (recipient.isSystemContact && !recipient.showVerified()) { + SpannableStringBuilder().apply { + val drawable = ContextUtil.requireDrawable(context, R.drawable.symbol_person_circle_24).apply { + setTint(ContextCompat.getColor(context, R.color.signal_colorOnSurface)) + } + SpanUtil.appendCenteredImageSpan(this, drawable, 16, 16) + } + } else { + null + } + name.setText(recipient, suffix) + badge.setBadgeFromRecipient(getRecipient(model)) bindAvatar(model) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java index c7f0e69399..7fae8c4364 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java @@ -19,6 +19,7 @@ package org.thoughtcrime.securesms.conversationlist; import android.content.Context; import android.graphics.Rect; import android.graphics.Typeface; +import android.graphics.drawable.Drawable; import android.text.Spannable; import android.text.SpannableString; import android.text.SpannableStringBuilder; @@ -78,6 +79,7 @@ import org.thoughtcrime.securesms.recipients.LiveRecipient; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.search.MessageResult; +import org.thoughtcrime.securesms.util.ContextUtil; import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.ExpirationUtil; import org.thoughtcrime.securesms.util.MediaUtil; @@ -211,7 +213,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind @NonNull Set typingThreads, @NonNull ConversationSet selectedConversations) { - bindThread(lifecycleOwner, thread, glideRequests, locale, typingThreads, selectedConversations, null); + bindThread(lifecycleOwner, thread, glideRequests, locale, typingThreads, selectedConversations, null, false); } public void bindThread(@NonNull LifecycleOwner lifecycleOwner, @@ -220,7 +222,8 @@ public final class ConversationListItem extends ConstraintLayout implements Bind @NonNull Locale locale, @NonNull Set typingThreads, @NonNull ConversationSet selectedConversations, - @Nullable String highlightSubstring) + @Nullable String highlightSubstring, + boolean appendSystemContactIcon) { this.threadId = thread.getThreadId(); this.requestManager = requestManager; @@ -234,12 +237,20 @@ public final class ConversationListItem extends ConstraintLayout implements Bind observeDisplayBody(null, null); joinMembersDisposable.dispose(); + SpannableStringBuilder suffix = null; + if (appendSystemContactIcon && recipient.get().isSystemContact() && !recipient.get().showVerified()) { + suffix = new SpannableStringBuilder(); + Drawable drawable = ContextUtil.requireDrawable(getContext(), R.drawable.symbol_person_circle_24); + drawable.setTint(ContextCompat.getColor(getContext(), R.color.signal_colorOnSurface)); + SpanUtil.appendCenteredImageSpan(suffix, drawable, 16, 16); + } + if (highlightSubstring != null) { String name = recipient.get().isSelf() ? getContext().getString(R.string.note_to_self) : recipient.get().getDisplayName(getContext()); - this.fromView.setText(recipient.get(), SearchUtil.getHighlightedSpan(locale, searchStyleFactory, name, highlightSubstring, SearchUtil.MATCH_ALL), true, null); + this.fromView.setText(recipient.get(), SearchUtil.getHighlightedSpan(locale, searchStyleFactory, name, highlightSubstring, SearchUtil.MATCH_ALL), suffix); } else { - this.fromView.setText(recipient.get(), false); + this.fromView.setText(recipient.get(), suffix); } this.typingThreads = typingThreads; @@ -299,7 +310,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind joinMembersDisposable.dispose(); setSubjectViewText(null); - fromView.setText(recipient.get(), recipient.get().getDisplayName(getContext()), false, null, false); + fromView.setText(recipient.get(), recipient.get().getDisplayName(getContext()), null, false); setSubjectViewText(SearchUtil.getHighlightedSpan(locale, searchStyleFactory, messageResult.getBodySnippet(), highlightSubstring, SearchUtil.MATCH_ALL)); updateDateView = () -> dateView.setText(DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, messageResult.getReceivedTimestampMs())); @@ -332,7 +343,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind setSubjectViewText(SearchUtil.getHighlightedSpan(locale, searchStyleFactory, joined, highlightSubstring, SearchUtil.MATCH_ALL)); }); - fromView.setText(recipient.get(), false); + fromView.setText(recipient.get()); updateDateView = () -> { if (groupWithMembers.getDate() > 0) { @@ -554,9 +565,9 @@ public final class ConversationListItem extends ConstraintLayout implements Bind } else { name = recipient.getDisplayName(getContext()); } - fromView.setText(recipient, SearchUtil.getHighlightedSpan(locale, searchStyleFactory, new SpannableString(name), highlightSubstring, SearchUtil.MATCH_ALL), true, null, thread != null); + fromView.setText(recipient, SearchUtil.getHighlightedSpan(locale, searchStyleFactory, new SpannableString(name), highlightSubstring, SearchUtil.MATCH_ALL), null, thread != null); } else { - fromView.setText(recipient, false); + fromView.setText(recipient); } contactPhotoImage.setAvatar(requestManager, recipient, !batchMode, false); setBadgeFromRecipient(recipient); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListSearchAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListSearchAdapter.kt index 9a23eeb37e..17c48c4169 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListSearchAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListSearchAdapter.kt @@ -120,7 +120,8 @@ class ConversationListSearchAdapter( Locale.getDefault(), emptySet(), ConversationSet(), - model.thread.query + model.thread.query, + true ) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraContactSelectionAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraContactSelectionAdapter.java index 752574f548..96e7214f7e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraContactSelectionAdapter.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraContactSelectionAdapter.java @@ -60,7 +60,7 @@ class CameraContactSelectionAdapter extends RecyclerView.Adapter { diff --git a/app/src/main/java/org/thoughtcrime/securesms/search/ContactSearchResult.kt b/app/src/main/java/org/thoughtcrime/securesms/search/ContactSearchResult.kt deleted file mode 100644 index d5fdb10c64..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/search/ContactSearchResult.kt +++ /dev/null @@ -1,5 +0,0 @@ -package org.thoughtcrime.securesms.search - -import org.thoughtcrime.securesms.recipients.Recipient - -data class ContactSearchResult(val results: List, val query: String) diff --git a/app/src/main/java/org/thoughtcrime/securesms/search/SearchRepository.java b/app/src/main/java/org/thoughtcrime/securesms/search/SearchRepository.java index be8c90db35..c70ca8c52f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/search/SearchRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/search/SearchRepository.java @@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.search; import android.content.Context; import android.database.Cursor; -import android.database.MergeCursor; import android.text.Spannable; import android.text.SpannableString; import android.text.SpannableStringBuilder; @@ -14,7 +13,6 @@ import androidx.annotation.WorkerThread; import org.signal.core.util.CursorUtil; import org.signal.core.util.StringUtil; -import org.signal.core.util.concurrent.LatestPrioritizedSerialExecutor; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.contacts.ContactRepository; @@ -52,7 +50,6 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.Executor; -import java.util.function.Consumer; import static org.thoughtcrime.securesms.database.SearchTable.SNIPPET_WRAP; @@ -72,8 +69,7 @@ public class SearchRepository { private final MentionTable mentionTable; private final MessageTable messageTable; - private final LatestPrioritizedSerialExecutor searchExecutor; - private final Executor serialExecutor; + private final Executor serialExecutor; public SearchRepository(@NonNull String noteToSelfTitle) { this.context = ApplicationDependencies.getApplication().getApplicationContext(); @@ -84,7 +80,6 @@ public class SearchRepository { this.mentionTable = SignalDatabase.mentions(); this.messageTable = SignalDatabase.messages(); this.contactRepository = new ContactRepository(context, noteToSelfTitle); - this.searchExecutor = new LatestPrioritizedSerialExecutor(SignalExecutors.BOUNDED); this.serialExecutor = new SerialExecutor(SignalExecutors.BOUNDED); } @@ -98,17 +93,6 @@ public class SearchRepository { return new ThreadSearchResult(result, query); } - public void queryContacts(@NonNull String query, @NonNull Consumer callback) { - searchExecutor.execute(1, () -> { - long start = System.currentTimeMillis(); - List result = queryContacts(query); - - Log.d(TAG, "[contacts] Search took " + (System.currentTimeMillis() - start) + " ms"); - - callback.accept(new ContactSearchResult(result, query)); - }); - } - @WorkerThread public @NonNull MessageSearchResult queryMessagesSync(@NonNull String query) { long start = System.currentTimeMillis(); @@ -139,27 +123,6 @@ public class SearchRepository { }); } - private List queryContacts(String query) { - if (Util.isEmpty(query)) { - return Collections.emptyList(); - } - - Cursor contacts = null; - - try { - Cursor textSecureContacts = contactRepository.querySignalContacts(query); - Cursor systemContacts = contactRepository.queryNonSignalContacts(query); - - contacts = new MergeCursor(new Cursor[] { textSecureContacts, systemContacts }); - - return readToList(contacts, new RecipientModelBuilder(), 250); - } finally { - if (contacts != null) { - contacts.close(); - } - } - } - private @NonNull List queryConversations(@NonNull String query, boolean unreadOnly) { if (Util.isEmpty(query)) { return Collections.emptyList(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/search/SearchResult.kt b/app/src/main/java/org/thoughtcrime/securesms/search/SearchResult.kt deleted file mode 100644 index 4099c93b4c..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/search/SearchResult.kt +++ /dev/null @@ -1,45 +0,0 @@ -package org.thoughtcrime.securesms.search - -import org.thoughtcrime.securesms.conversationlist.model.ConversationFilter -import org.thoughtcrime.securesms.database.model.ThreadRecord -import org.thoughtcrime.securesms.recipients.Recipient - -/** - * Represents an all-encompassing search result that can contain various result for different - * subcategories. - */ -data class SearchResult( - val query: String, - val contacts: List, - val conversations: List, - val messages: List, - val conversationFilter: ConversationFilter -) { - fun size(): Int { - return contacts.size + conversations.size + messages.size - } - - val isEmpty: Boolean - get() = size() == 0 - - fun merge(result: ContactSearchResult): SearchResult { - return this.copy(contacts = result.results, query = result.query) - } - - fun merge(result: ThreadSearchResult): SearchResult { - return this.copy(conversations = result.results, query = result.query) - } - - fun merge(result: MessageSearchResult): SearchResult { - return this.copy(messages = result.results, query = result.query) - } - - fun merge(conversationFilter: ConversationFilter): SearchResult { - return this.copy(conversationFilter = conversationFilter) - } - - companion object { - @JvmField - val EMPTY = SearchResult("", emptyList(), emptyList(), emptyList(), ConversationFilter.OFF) - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/SpanUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/SpanUtil.java index d0c63c7798..f97c23b6da 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/SpanUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/SpanUtil.java @@ -147,11 +147,6 @@ public final class SpanUtil { builder.append(" ").append(SpanUtil.buildCenteredImageSpan(drawable)); } - public static void appendBottomImageSpan(@NonNull SpannableStringBuilder builder, @NonNull Drawable drawable, int width, int height) { - drawable.setBounds(0, 0, ViewUtil.dpToPx(width), ViewUtil.dpToPx(height)); - builder.append(SpanUtil.buildImageSpan(drawable, DynamicDrawableSpan.ALIGN_BOTTOM)); - } - public static CharSequence learnMore(@NonNull Context context, @ColorInt int color, @NonNull View.OnClickListener onLearnMoreClicked) diff --git a/app/src/main/res/drawable/symbol_chevron_right_24_color_on_secondary_container.xml b/app/src/main/res/drawable/symbol_chevron_right_24_color_on_secondary_container.xml deleted file mode 100644 index ba3faecca6..0000000000 --- a/app/src/main/res/drawable/symbol_chevron_right_24_color_on_secondary_container.xml +++ /dev/null @@ -1,10 +0,0 @@ - - -