diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/ConversationScrollToView.java b/app/src/main/java/org/thoughtcrime/securesms/components/ConversationScrollToView.java index dfe03192c..8dd0ae69c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/ConversationScrollToView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/ConversationScrollToView.java @@ -36,7 +36,7 @@ public final class ConversationScrollToView extends FrameLayout { unreadCount = findViewById(R.id.conversation_scroll_to_count); scrollButton = findViewById(R.id.conversation_scroll_to_button); - if (attrs != null) { + if (attrs != null && !isInEditMode()) { TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ConversationScrollToView); int srcId = array.getResourceId(R.styleable.ConversationScrollToView_cstv_scroll_button_src, 0); diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SimpleEmojiTextView.kt b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SimpleEmojiTextView.kt index cb27a842f..172cba075 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SimpleEmojiTextView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SimpleEmojiTextView.kt @@ -18,7 +18,7 @@ open class SimpleEmojiTextView @JvmOverloads constructor( private val sizeChangeDebouncer: ThrottledDebouncer = ThrottledDebouncer(200) init { - isEmojiCompatEnabled = SignalStore.settings().isPreferSystemEmoji + isEmojiCompatEnabled = isInEditMode || SignalStore.settings().isPreferSystemEmoji } override fun setText(text: CharSequence?, type: BufferType?) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java index c5f7941fa..06bcea666 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java @@ -357,9 +357,9 @@ public class ConversationFragment extends LoggingFragment implements Multiselect giphyMp4ProjectionRecycler = initializeGiphyMp4(); - this.groupViewModel = new ViewModelProvider(getParentFragment(), new ConversationGroupViewModel.Factory()).get(ConversationGroupViewModel.class); + this.groupViewModel = new ViewModelProvider(getParentFragment(), (ViewModelProvider.Factory) new ConversationGroupViewModel.Factory()).get(ConversationGroupViewModel.class); this.messageCountsViewModel = new ViewModelProvider(getParentFragment()).get(MessageCountsViewModel.class); - this.conversationViewModel = new ViewModelProvider(getParentFragment(), new ConversationViewModel.Factory()).get(ConversationViewModel.class); + this.conversationViewModel = new ViewModelProvider(getParentFragment(), (ViewModelProvider.Factory) new ConversationViewModel.Factory()).get(ConversationViewModel.class); disposables.add(conversationViewModel.getChatColors().subscribe(chatColors -> { recyclerViewColorizer.setChatColors(chatColors); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListArchiveFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListArchiveFragment.java index 2945e51b2..4c2697f55 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListArchiveFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListArchiveFragment.java @@ -124,7 +124,7 @@ public class ConversationListArchiveFragment extends ConversationListFragment im @SuppressLint("StaticFieldLeak") @Override - protected void onItemSwiped(long threadId, int unreadCount) { + protected void onItemSwiped(long threadId, int unreadCount, int unreadSelfMentionsCount) { archiveDecoration.onArchiveStarted(); itemAnimator.enable(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java index 13102fb9b..767803eb2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java @@ -40,7 +40,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.FrameLayout; -import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; @@ -76,6 +75,7 @@ import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import org.signal.core.util.DimensionUnit; +import org.signal.core.util.Stopwatch; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.concurrent.SimpleTask; import org.signal.core.util.logging.Log; @@ -156,7 +156,6 @@ import org.thoughtcrime.securesms.util.SignalLocalMetrics; import org.thoughtcrime.securesms.util.SignalProxyUtil; import org.thoughtcrime.securesms.util.SnapToTopDataObserver; import org.thoughtcrime.securesms.util.StickyHeaderDecoration; -import org.signal.core.util.Stopwatch; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; @@ -1394,7 +1393,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode } @SuppressLint("StaticFieldLeak") - protected void onItemSwiped(long threadId, int unreadCount) { + protected void onItemSwiped(long threadId, int unreadCount, int unreadSelfMentionsCount) { archiveDecoration.onArchiveStarted(); itemAnimator.enable(); @@ -1434,7 +1433,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode threadDatabase.restorePins(pinnedThreadIds); if (unreadCount > 0) { - threadDatabase.incrementUnread(threadId, unreadCount); + threadDatabase.incrementUnread(threadId, unreadCount, unreadSelfMentionsCount); ApplicationDependencies.getMessageNotifier().updateNotification(context); } @@ -1558,10 +1557,9 @@ public class ConversationListFragment extends MainFragment implements ActionMode } private void onTrueSwipe(RecyclerView.ViewHolder viewHolder) { - final long threadId = ((ConversationListItem) viewHolder.itemView).getThreadId(); - final int unreadCount = ((ConversationListItem) viewHolder.itemView).getUnreadCount(); + ThreadRecord thread = ((ConversationListItem) viewHolder.itemView).getThread(); - onItemSwiped(threadId, unreadCount); + onItemSwiped(thread.getThreadId(), thread.getUnreadCount(), thread.getUnreadSelfMentionsCount()); } @Override 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 1fd3f28d4..de4ace0bb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java @@ -117,6 +117,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind private View checkContainer; private View uncheckedView; private View checkedView; + private View unreadMentions; private int thumbSize; private GlideLiveDataTarget thumbTarget; @@ -149,6 +150,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind this.checkContainer = findViewById(R.id.conversation_list_item_check_container); this.uncheckedView = findViewById(R.id.conversation_list_item_unchecked); this.checkedView = findViewById(R.id.conversation_list_item_checked); + this.unreadMentions = findViewById(R.id.conversation_list_item_unread_mentions_indicator); this.thumbSize = (int) DimensionUnit.SP.toPixels(16f); this.thumbTarget = new GlideLiveDataTarget(thumbSize, thumbSize); @@ -277,6 +279,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind dateView.setText(""); archivedView.setVisibility(GONE); unreadIndicator.setVisibility(GONE); + unreadMentions.setVisibility(GONE); deliveryStatusIndicator.setNone(); alertView.setNone(); @@ -304,6 +307,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind dateView.setText(DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, messageResult.getReceivedTimestampMs())); archivedView.setVisibility(GONE); unreadIndicator.setVisibility(GONE); + unreadMentions.setVisibility(GONE); deliveryStatusIndicator.setNone(); alertView.setNone(); @@ -464,11 +468,19 @@ public final class ConversationListItem extends ConstraintLayout implements Bind private void setUnreadIndicator(ThreadRecord thread) { if (thread.isRead()) { unreadIndicator.setVisibility(View.GONE); + unreadMentions.setVisibility(View.GONE); return; } + if (thread.getUnreadSelfMentionsCount() > 0) { + unreadMentions.setVisibility(View.VISIBLE); + unreadIndicator.setVisibility(thread.getUnreadCount() == 1 ? View.GONE : View.VISIBLE); + } else { + unreadMentions.setVisibility(View.GONE); + unreadIndicator.setVisibility(View.VISIBLE); + } + unreadIndicator.setText(unreadCount > 0 ? String.valueOf(unreadCount) : " "); - unreadIndicator.setVisibility(View.VISIBLE); } private void onRecipientChanged(@NonNull Recipient recipient) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java index 8feab7029..03d8407c2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -1988,7 +1988,8 @@ public class MmsDatabase extends MessageDatabase { boolean isNotStoryGroupReply = retrieved.getParentStoryId() == null || !retrieved.getParentStoryId().isGroupReply(); if (!Types.isExpirationTimerUpdate(mailbox) && !retrieved.getStoryType().isStory() && isNotStoryGroupReply) { - SignalDatabase.threads().incrementUnread(threadId, 1); + boolean incrementUnreadMentions = !retrieved.getMentions().isEmpty() && retrieved.getMentions().stream().anyMatch(m -> m.getRecipientId().equals(Recipient.self().getId())); + SignalDatabase.threads().incrementUnread(threadId, 1, incrementUnreadMentions ? 1 : 0); SignalDatabase.threads().update(threadId, true); } @@ -2098,7 +2099,7 @@ public class MmsDatabase extends MessageDatabase { notifyConversationListeners(threadId); if (org.thoughtcrime.securesms.util.Util.isDefaultSmsProvider(context)) { - SignalDatabase.threads().incrementUnread(threadId, 1); + SignalDatabase.threads().incrementUnread(threadId, 1, 0); } SignalDatabase.threads().update(threadId, true); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java index 3a3577f60..2595c013b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -741,7 +741,7 @@ public class SmsDatabase extends MessageDatabase { db.insert(TABLE_NAME, null, values); - SignalDatabase.threads().incrementUnread(threadId, 1); + SignalDatabase.threads().incrementUnread(threadId, 1, 0); } SignalDatabase.threads().update(threadId, true); @@ -818,7 +818,7 @@ public class SmsDatabase extends MessageDatabase { db.insert(TABLE_NAME, null, values); - SignalDatabase.threads().incrementUnread(threadId, 1); + SignalDatabase.threads().incrementUnread(threadId, 1, 0); } SignalDatabase.threads().update(threadId, true); @@ -890,7 +890,7 @@ public class SmsDatabase extends MessageDatabase { long messageId = db.insert(TABLE_NAME, null, values); if (unread) { - SignalDatabase.threads().incrementUnread(threadId, 1); + SignalDatabase.threads().incrementUnread(threadId, 1, 0); } SignalDatabase.threads().update(threadId, true); @@ -1278,7 +1278,7 @@ public class SmsDatabase extends MessageDatabase { long messageId = db.insert(TABLE_NAME, null, values); if (unread) { - SignalDatabase.threads().incrementUnread(threadId, 1); + SignalDatabase.threads().incrementUnread(threadId, 1, 0); } if (!silent) { @@ -1324,7 +1324,7 @@ public class SmsDatabase extends MessageDatabase { long messageId = db.insert(TABLE_NAME, null, values); - SignalDatabase.threads().incrementUnread(threadId, 1); + SignalDatabase.threads().incrementUnread(threadId, 1, 0); SignalDatabase.threads().update(threadId, true); notifyConversationListeners(threadId); @@ -1348,7 +1348,7 @@ public class SmsDatabase extends MessageDatabase { databaseHelper.getSignalWritableDatabase().insert(TABLE_NAME, null, values); - SignalDatabase.threads().incrementUnread(threadId, 1); + SignalDatabase.threads().incrementUnread(threadId, 1, 0); SignalDatabase.threads().update(threadId, true); notifyConversationListeners(threadId); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java index 88ab16c1c..1a9512e27 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -94,54 +94,56 @@ public class ThreadDatabase extends Database { public static final long NO_TRIM_BEFORE_DATE_SET = 0; public static final int NO_TRIM_MESSAGE_COUNT_SET = Integer.MAX_VALUE; - public static final String TABLE_NAME = "thread"; - public static final String ID = "_id"; - public static final String DATE = "date"; - public static final String MEANINGFUL_MESSAGES = "message_count"; - public static final String RECIPIENT_ID = "thread_recipient_id"; - public static final String SNIPPET = "snippet"; - private static final String SNIPPET_CHARSET = "snippet_charset"; - public static final String READ = "read"; - public static final String UNREAD_COUNT = "unread_count"; - public static final String TYPE = "type"; - private static final String ERROR = "error"; - public static final String SNIPPET_TYPE = "snippet_type"; - public static final String SNIPPET_URI = "snippet_uri"; - public static final String SNIPPET_CONTENT_TYPE = "snippet_content_type"; - public static final String SNIPPET_EXTRAS = "snippet_extras"; - public static final String ARCHIVED = "archived"; - public static final String STATUS = "status"; - public static final String DELIVERY_RECEIPT_COUNT = "delivery_receipt_count"; - public static final String READ_RECEIPT_COUNT = "read_receipt_count"; - public static final String EXPIRES_IN = "expires_in"; - public static final String LAST_SEEN = "last_seen"; - public static final String HAS_SENT = "has_sent"; - private static final String LAST_SCROLLED = "last_scrolled"; - static final String PINNED = "pinned"; + public static final String TABLE_NAME = "thread"; + public static final String ID = "_id"; + public static final String DATE = "date"; + public static final String MEANINGFUL_MESSAGES = "message_count"; + public static final String RECIPIENT_ID = "thread_recipient_id"; + public static final String SNIPPET = "snippet"; + private static final String SNIPPET_CHARSET = "snippet_charset"; + public static final String READ = "read"; + public static final String UNREAD_COUNT = "unread_count"; + public static final String TYPE = "type"; + private static final String ERROR = "error"; + public static final String SNIPPET_TYPE = "snippet_type"; + public static final String SNIPPET_URI = "snippet_uri"; + public static final String SNIPPET_CONTENT_TYPE = "snippet_content_type"; + public static final String SNIPPET_EXTRAS = "snippet_extras"; + public static final String ARCHIVED = "archived"; + public static final String STATUS = "status"; + public static final String DELIVERY_RECEIPT_COUNT = "delivery_receipt_count"; + public static final String READ_RECEIPT_COUNT = "read_receipt_count"; + public static final String EXPIRES_IN = "expires_in"; + public static final String LAST_SEEN = "last_seen"; + public static final String HAS_SENT = "has_sent"; + private static final String LAST_SCROLLED = "last_scrolled"; + static final String PINNED = "pinned"; + private static final String UNREAD_SELF_MENTION_COUNT = "unread_self_mention_count"; - public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + - DATE + " INTEGER DEFAULT 0, " + - MEANINGFUL_MESSAGES + " INTEGER DEFAULT 0, " + - RECIPIENT_ID + " INTEGER, " + - SNIPPET + " TEXT, " + - SNIPPET_CHARSET + " INTEGER DEFAULT 0, " + - READ + " INTEGER DEFAULT " + ReadStatus.READ.serialize() + ", " + - TYPE + " INTEGER DEFAULT 0, " + - ERROR + " INTEGER DEFAULT 0, " + - SNIPPET_TYPE + " INTEGER DEFAULT 0, " + - SNIPPET_URI + " TEXT DEFAULT NULL, " + - SNIPPET_CONTENT_TYPE + " TEXT DEFAULT NULL, " + - SNIPPET_EXTRAS + " TEXT DEFAULT NULL, " + - ARCHIVED + " INTEGER DEFAULT 0, " + - STATUS + " INTEGER DEFAULT 0, " + - DELIVERY_RECEIPT_COUNT + " INTEGER DEFAULT 0, " + - EXPIRES_IN + " INTEGER DEFAULT 0, " + - LAST_SEEN + " INTEGER DEFAULT 0, " + - HAS_SENT + " INTEGER DEFAULT 0, " + - READ_RECEIPT_COUNT + " INTEGER DEFAULT 0, " + - UNREAD_COUNT + " INTEGER DEFAULT 0, " + - LAST_SCROLLED + " INTEGER DEFAULT 0, " + - PINNED + " INTEGER DEFAULT 0);"; + public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + DATE + " INTEGER DEFAULT 0, " + + MEANINGFUL_MESSAGES + " INTEGER DEFAULT 0, " + + RECIPIENT_ID + " INTEGER, " + + SNIPPET + " TEXT, " + + SNIPPET_CHARSET + " INTEGER DEFAULT 0, " + + READ + " INTEGER DEFAULT " + ReadStatus.READ.serialize() + ", " + + TYPE + " INTEGER DEFAULT 0, " + + ERROR + " INTEGER DEFAULT 0, " + + SNIPPET_TYPE + " INTEGER DEFAULT 0, " + + SNIPPET_URI + " TEXT DEFAULT NULL, " + + SNIPPET_CONTENT_TYPE + " TEXT DEFAULT NULL, " + + SNIPPET_EXTRAS + " TEXT DEFAULT NULL, " + + ARCHIVED + " INTEGER DEFAULT 0, " + + STATUS + " INTEGER DEFAULT 0, " + + DELIVERY_RECEIPT_COUNT + " INTEGER DEFAULT 0, " + + EXPIRES_IN + " INTEGER DEFAULT 0, " + + LAST_SEEN + " INTEGER DEFAULT 0, " + + HAS_SENT + " INTEGER DEFAULT 0, " + + READ_RECEIPT_COUNT + " INTEGER DEFAULT 0, " + + UNREAD_COUNT + " INTEGER DEFAULT 0, " + + LAST_SCROLLED + " INTEGER DEFAULT 0, " + + PINNED + " INTEGER DEFAULT 0, " + + UNREAD_SELF_MENTION_COUNT + " INTEGER DEFAULT 0);"; public static final String[] CREATE_INDEXS = { "CREATE INDEX IF NOT EXISTS thread_recipient_id_index ON " + TABLE_NAME + " (" + RECIPIENT_ID + ");", @@ -151,7 +153,8 @@ public class ThreadDatabase extends Database { private static final String[] THREAD_PROJECTION = { ID, DATE, MEANINGFUL_MESSAGES, RECIPIENT_ID, SNIPPET, SNIPPET_CHARSET, READ, UNREAD_COUNT, TYPE, ERROR, SNIPPET_TYPE, - SNIPPET_URI, SNIPPET_CONTENT_TYPE, SNIPPET_EXTRAS, ARCHIVED, STATUS, DELIVERY_RECEIPT_COUNT, EXPIRES_IN, LAST_SEEN, READ_RECEIPT_COUNT, LAST_SCROLLED, PINNED + SNIPPET_URI, SNIPPET_CONTENT_TYPE, SNIPPET_EXTRAS, ARCHIVED, STATUS, DELIVERY_RECEIPT_COUNT, EXPIRES_IN, LAST_SEEN, + READ_RECEIPT_COUNT, LAST_SCROLLED, PINNED, UNREAD_SELF_MENTION_COUNT }; private static final List TYPED_THREAD_PROJECTION = Stream.of(THREAD_PROJECTION) @@ -371,6 +374,7 @@ public class ThreadDatabase extends Database { ContentValues contentValues = new ContentValues(1); contentValues.put(READ, ReadStatus.READ.serialize()); contentValues.put(UNREAD_COUNT, 0); + contentValues.put(UNREAD_SELF_MENTION_COUNT, 0); db.update(TABLE_NAME, contentValues, null, null); @@ -464,9 +468,11 @@ public class ThreadDatabase extends Database { SignalDatabase.mms().setReactionsSeen(threadId, sinceTimestamp); int unreadCount = SignalDatabase.mmsSms().getUnreadCount(threadId); - contentValues.put(UNREAD_COUNT, unreadCount); + int unreadMentionsCount = SignalDatabase.mms().getUnreadMentionCount(threadId); + contentValues.put(UNREAD_SELF_MENTION_COUNT, unreadMentionsCount); + db.update(TABLE_NAME, contentValues, ID_WHERE, SqlUtil.buildArgs(threadId)); if (previous != null && previous.isForcedUnread()) { @@ -549,14 +555,15 @@ public class ThreadDatabase extends Database { } } - public void incrementUnread(long threadId, int amount) { + public void incrementUnread(long threadId, int unreadAmount, int unreadSelfMentionAmount) { SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); db.execSQL("UPDATE " + TABLE_NAME + " SET " + READ + " = " + ReadStatus.UNREAD.serialize() + ", " + UNREAD_COUNT + " = " + UNREAD_COUNT + " + ?, " + + UNREAD_SELF_MENTION_COUNT + " = " + UNREAD_SELF_MENTION_COUNT + " + ?, " + LAST_SCROLLED + " = ? " + "WHERE " + ID + " = ?", - SqlUtil.buildArgs(amount, 0, threadId)); + SqlUtil.buildArgs(unreadAmount, unreadSelfMentionAmount, 0, threadId)); } public void setDistributionType(long threadId, int distributionType) { @@ -1223,12 +1230,14 @@ public class ThreadDatabase extends Database { } void updateReadState(long threadId) { - ThreadRecord previous = getThreadRecord(threadId); - int unreadCount = SignalDatabase.mmsSms().getUnreadCount(threadId); + ThreadRecord previous = getThreadRecord(threadId); + int unreadCount = SignalDatabase.mmsSms().getUnreadCount(threadId); + int unreadMentionsCount = SignalDatabase.mms().getUnreadMentionCount(threadId); ContentValues contentValues = new ContentValues(); contentValues.put(READ, unreadCount == 0 ? ReadStatus.READ.serialize() : ReadStatus.UNREAD.serialize()); contentValues.put(UNREAD_COUNT, unreadCount); + contentValues.put(UNREAD_SELF_MENTION_COUNT, unreadMentionsCount); databaseHelper.getSignalWritableDatabase().update(TABLE_NAME, contentValues, ID_WHERE, SqlUtil.buildArgs(threadId)); @@ -1316,10 +1325,12 @@ public class ThreadDatabase extends Database { values.put(READ, ReadStatus.FORCED_UNREAD.serialize()); } else { if (threadId != null) { - int unreadCount = SignalDatabase.mmsSms().getUnreadCount(threadId); + int unreadCount = SignalDatabase.mmsSms().getUnreadCount(threadId); + int unreadMentionsCount = SignalDatabase.mms().getUnreadMentionCount(threadId); values.put(READ, unreadCount == 0 ? ReadStatus.READ.serialize() : ReadStatus.UNREAD.serialize()); values.put(UNREAD_COUNT, unreadCount); + values.put(UNREAD_SELF_MENTION_COUNT, unreadMentionsCount); } } @@ -1723,6 +1734,7 @@ public class ThreadDatabase extends Database { .setUnreadCount(cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.UNREAD_COUNT))) .setForcedUnread(cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.READ)) == ReadStatus.FORCED_UNREAD.serialize()) .setPinned(CursorUtil.requireBoolean(cursor, ThreadDatabase.PINNED)) + .setUnreadSelfMentionsCount(CursorUtil.requireInt(cursor, ThreadDatabase.UNREAD_SELF_MENTION_COUNT)) .setExtra(extra) .build(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java index a15d2138f..31f98ce78 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java @@ -56,27 +56,29 @@ public final class ThreadRecord { private final long expiresIn; private final long lastSeen; private final boolean isPinned; + private final int unreadSelfMentionsCount; private ThreadRecord(@NonNull Builder builder) { - this.threadId = builder.threadId; - this.body = builder.body; - this.recipient = builder.recipient; - this.date = builder.date; - this.type = builder.type; - this.deliveryStatus = builder.deliveryStatus; - this.deliveryReceiptCount = builder.deliveryReceiptCount; - this.readReceiptCount = builder.readReceiptCount; - this.snippetUri = builder.snippetUri; - this.contentType = builder.contentType; - this.extra = builder.extra; - this.meaningfulMessages = builder.meaningfulMessages; - this.unreadCount = builder.unreadCount; - this.forcedUnread = builder.forcedUnread; - this.distributionType = builder.distributionType; - this.archived = builder.archived; - this.expiresIn = builder.expiresIn; - this.lastSeen = builder.lastSeen; - this.isPinned = builder.isPinned; + this.threadId = builder.threadId; + this.body = builder.body; + this.recipient = builder.recipient; + this.date = builder.date; + this.type = builder.type; + this.deliveryStatus = builder.deliveryStatus; + this.deliveryReceiptCount = builder.deliveryReceiptCount; + this.readReceiptCount = builder.readReceiptCount; + this.snippetUri = builder.snippetUri; + this.contentType = builder.contentType; + this.extra = builder.extra; + this.meaningfulMessages = builder.meaningfulMessages; + this.unreadCount = builder.unreadCount; + this.forcedUnread = builder.forcedUnread; + this.distributionType = builder.distributionType; + this.archived = builder.archived; + this.expiresIn = builder.expiresIn; + this.lastSeen = builder.lastSeen; + this.isPinned = builder.isPinned; + this.unreadSelfMentionsCount = builder.unreadSelfMentionsCount; } public long getThreadId() { @@ -103,10 +105,6 @@ public final class ThreadRecord { return contentType; } - public boolean hasMeaningfulMessages() { - return meaningfulMessages; - } - public int getUnreadCount() { return unreadCount; } @@ -207,10 +205,6 @@ public final class ThreadRecord { } } - public boolean isGv2Invite() { - return extra != null && extra.isGv2Invite(); - } - public boolean isMessageRequestAccepted() { if (extra != null) return extra.isMessageRequestAccepted(); else return true; @@ -220,29 +214,34 @@ public final class ThreadRecord { return isPinned; } + public int getUnreadSelfMentionsCount() { + return unreadSelfMentionsCount; + } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ThreadRecord that = (ThreadRecord) o; - return threadId == that.threadId && - type == that.type && - date == that.date && - deliveryStatus == that.deliveryStatus && + return threadId == that.threadId && + type == that.type && + date == that.date && + deliveryStatus == that.deliveryStatus && deliveryReceiptCount == that.deliveryReceiptCount && - readReceiptCount == that.readReceiptCount && - meaningfulMessages == that.meaningfulMessages && - unreadCount == that.unreadCount && - forcedUnread == that.forcedUnread && - distributionType == that.distributionType && - archived == that.archived && - expiresIn == that.expiresIn && - lastSeen == that.lastSeen && - isPinned == that.isPinned && - body.equals(that.body) && - recipient.equals(that.recipient) && - Objects.equals(snippetUri, that.snippetUri) && - Objects.equals(contentType, that.contentType) && + readReceiptCount == that.readReceiptCount && + meaningfulMessages == that.meaningfulMessages && + unreadCount == that.unreadCount && + forcedUnread == that.forcedUnread && + distributionType == that.distributionType && + archived == that.archived && + expiresIn == that.expiresIn && + lastSeen == that.lastSeen && + isPinned == that.isPinned && + body.equals(that.body) && + recipient.equals(that.recipient) && + unreadSelfMentionsCount == that.unreadSelfMentionsCount && + Objects.equals(snippetUri, that.snippetUri) && + Objects.equals(contentType, that.contentType) && Objects.equals(extra, that.extra); } @@ -266,7 +265,8 @@ public final class ThreadRecord { archived, expiresIn, lastSeen, - isPinned); + isPinned, + unreadSelfMentionsCount); } public static class Builder { @@ -289,6 +289,7 @@ public final class ThreadRecord { private long expiresIn; private long lastSeen; private boolean isPinned; + private int unreadSelfMentionsCount; public Builder(long threadId) { this.threadId = threadId; @@ -389,6 +390,11 @@ public final class ThreadRecord { return this; } + public Builder setUnreadSelfMentionsCount(int unreadSelfMentionsCount) { + this.unreadSelfMentionsCount = unreadSelfMentionsCount; + return this; + } + public ThreadRecord build() { if (distributionType == ThreadDatabase.DistributionTypes.CONVERSATION) { Preconditions.checkArgument(threadId > 0); diff --git a/app/src/main/res/drawable/ic_at_12.xml b/app/src/main/res/drawable/ic_at_12.xml new file mode 100644 index 000000000..10e72bc33 --- /dev/null +++ b/app/src/main/res/drawable/ic_at_12.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_at_20.xml b/app/src/main/res/drawable/ic_at_20.xml new file mode 100644 index 000000000..7140becf8 --- /dev/null +++ b/app/src/main/res/drawable/ic_at_20.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/conversation_fragment.xml b/app/src/main/res/layout/conversation_fragment.xml index c3211bb29..fb6b7750c 100644 --- a/app/src/main/res/layout/conversation_fragment.xml +++ b/app/src/main/res/layout/conversation_fragment.xml @@ -73,10 +73,11 @@ android:layout_marginEnd="10dp" android:layout_marginBottom="12dp" android:visibility="invisible" - app:cstv_scroll_button_src="@drawable/ic_at_24" + app:cstv_scroll_button_src="@drawable/ic_at_20" app:layout_constraintBottom_toTopOf="@id/scroll_to_bottom" app:layout_constraintEnd_toEndOf="parent" - app:layout_goneMarginBottom="20dp" /> + app:layout_goneMarginBottom="20dp" + tools:visibility="visible" /> + app:layout_constraintEnd_toEndOf="parent" + tools:visibility="visible" /> @@ -147,12 +148,27 @@ android:layout_gravity="center_vertical" app:iconColor="@color/signal_colorOnSurfaceVariant" /> + +