diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index 3140f5dea5..09a9881a9c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -124,7 +124,6 @@ import org.thoughtcrime.securesms.mms.MediaConstraints import org.thoughtcrime.securesms.mms.Slide import org.thoughtcrime.securesms.mms.SlideDeck import org.thoughtcrime.securesms.mms.VideoSlide -import org.thoughtcrime.securesms.notifications.MarkReadReceiver import org.thoughtcrime.securesms.permissions.Permissions import org.thoughtcrime.securesms.util.ActivityDispatcher import org.thoughtcrime.securesms.util.DateUtils @@ -310,7 +309,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe override fun onResume() { super.onResume() ApplicationContext.getInstance(this).messageNotifier.setVisibleThread(viewModel.threadId) - markAllAsRead() + threadDb.markAllAsRead(viewModel.threadId, viewModel.recipient.isOpenGroupRecipient) } override fun onPause() { @@ -555,18 +554,6 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe } } - private fun markAllAsRead() { - val messages = threadDb.setRead(viewModel.threadId, true) - if (viewModel.recipient.isGroupRecipient) { - for (message in messages) { - MarkReadReceiver.scheduleDeletion(this, message.expirationInfo) - } - } else { - MarkReadReceiver.process(this, messages) - } - ApplicationContext.getInstance(this).messageNotifier.updateNotification(this, false, 0) - } - override fun inputBarHeightChanged(newValue: Int) { @Suppress("NAME_SHADOWING") val newValue = max(newValue, resources.getDimension(R.dimen.input_bar_height).roundToInt()) // 36 DP is the exact height of the typing indicator view. It's also exactly 18 * 2, and 18 is the large message 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 2aa02a80d9..058345dcf5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -45,6 +45,7 @@ import org.session.libsession.utilities.recipients.Recipient.RecipientSettings; import org.session.libsignal.utilities.Log; import org.session.libsignal.utilities.Pair; import org.session.libsignal.utilities.guava.Optional; +import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.contactshare.ContactUtil; import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; @@ -55,6 +56,7 @@ import org.thoughtcrime.securesms.database.model.ThreadRecord; import org.thoughtcrime.securesms.dependencies.DatabaseComponent; import org.thoughtcrime.securesms.mms.Slide; import org.thoughtcrime.securesms.mms.SlideDeck; +import org.thoughtcrime.securesms.notifications.MarkReadReceiver; import org.thoughtcrime.securesms.util.SessionMetaProtocol; import java.io.Closeable; @@ -593,6 +595,18 @@ public class ThreadDatabase extends Database { notifyConversationListeners(threadId); } + public void markAllAsRead(long threadId, boolean isGroupRecipient) { + List messages = setRead(threadId, true); + if (isGroupRecipient) { + for (MarkedMessageInfo message: messages) { + MarkReadReceiver.scheduleDeletion(context, message.getExpirationInfo()); + } + } else { + MarkReadReceiver.process(context, messages); + } + ApplicationContext.getInstance(context).messageNotifier.updateNotification(context, false, 0); + } + private boolean deleteThreadOnEmpty(long threadId) { Recipient threadRecipient = getRecipientForThreadId(threadId); return threadRecipient != null && !threadRecipient.isOpenGroupRecipient(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt index 1d5580be36..01a1a3241e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt @@ -24,6 +24,7 @@ class ConversationOptionsBottomSheet : BottomSheetDialogFragment(), View.OnClick var onBlockTapped: (() -> Unit)? = null var onUnblockTapped: (() -> Unit)? = null var onDeleteTapped: (() -> Unit)? = null + var onMarkAllAsReadTapped: (() -> Unit)? = null var onNotificationTapped: (() -> Unit)? = null var onSetMuteTapped: ((Boolean) -> Unit)? = null @@ -40,6 +41,7 @@ class ConversationOptionsBottomSheet : BottomSheetDialogFragment(), View.OnClick binding.blockTextView -> onBlockTapped?.invoke() binding.unblockTextView -> onUnblockTapped?.invoke() binding.deleteTextView -> onDeleteTapped?.invoke() + binding.markAllAsReadTextView -> onMarkAllAsReadTapped?.invoke() binding.notificationsTextView -> onNotificationTapped?.invoke() binding.unMuteNotificationsTextView -> onSetMuteTapped?.invoke(false) binding.muteNotificationsTextView -> onSetMuteTapped?.invoke(true) @@ -67,6 +69,8 @@ class ConversationOptionsBottomSheet : BottomSheetDialogFragment(), View.OnClick binding.notificationsTextView.isVisible = recipient.isGroupRecipient && !recipient.isMuted binding.notificationsTextView.setOnClickListener(this) binding.deleteTextView.setOnClickListener(this) + binding.markAllAsReadTextView.isVisible = thread.unreadCount > 0 + binding.markAllAsReadTextView.setOnClickListener(this) binding.pinTextView.isVisible = !thread.isPinned binding.unpinTextView.isVisible = thread.isPinned binding.pinTextView.setOnClickListener(this) diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index a1a4a22adf..6882199165 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -34,6 +34,7 @@ import org.session.libsession.messaging.sending_receiving.MessageSender import org.session.libsession.utilities.GroupUtil import org.session.libsession.utilities.ProfilePictureModifiedEvent import org.session.libsession.utilities.TextSecurePreferences +import org.session.libsignal.utilities.ThreadUtils import org.session.libsignal.utilities.toHexString import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.MuteDialog @@ -52,6 +53,7 @@ import org.thoughtcrime.securesms.groups.JoinPublicChatActivity import org.thoughtcrime.securesms.groups.OpenGroupManager import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.mms.GlideRequests +import org.thoughtcrime.securesms.notifications.MarkReadReceiver import org.thoughtcrime.securesms.onboarding.SeedActivity import org.thoughtcrime.securesms.onboarding.SeedReminderViewDelegate import org.thoughtcrime.securesms.preferences.SettingsActivity @@ -296,6 +298,10 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis bottomSheet.dismiss() setConversationPinned(thread.threadId, false) } + bottomSheet.onMarkAllAsReadTapped = { + bottomSheet.dismiss() + markAllAsRead(thread) + } bottomSheet.show(supportFragmentManager, bottomSheet.tag) } @@ -369,6 +375,12 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis } } + private fun markAllAsRead(thread: ThreadRecord) { + ThreadUtils.queue { + threadDb.markAllAsRead(thread.threadId, thread.recipient.isOpenGroupRecipient) + } + } + private fun deleteConversation(thread: ThreadRecord) { val threadID = thread.threadId val recipient = thread.recipient diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java index 8ba364b7a5..90be1fc3dc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java @@ -70,12 +70,13 @@ public class MarkReadReceiver extends BroadcastReceiver { public static void process(@NonNull Context context, @NonNull List markedReadMessages) { if (markedReadMessages.isEmpty()) return; - if (!TextSecurePreferences.isReadReceiptsEnabled(context)) return; for (MarkedMessageInfo messageInfo : markedReadMessages) { scheduleDeletion(context, messageInfo.getExpirationInfo()); } + if (!TextSecurePreferences.isReadReceiptsEnabled(context)) return; + Map> addressMap = Stream.of(markedReadMessages) .map(MarkedMessageInfo::getSyncMessageId) .collect(Collectors.groupingBy(SyncMessageId::getAddress)); diff --git a/app/src/main/res/drawable/ic_outline_mark_chat_read_24.xml b/app/src/main/res/drawable/ic_outline_mark_chat_read_24.xml new file mode 100644 index 0000000000..28f57645ae --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_mark_chat_read_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/fragment_conversation_bottom_sheet.xml b/app/src/main/res/layout/fragment_conversation_bottom_sheet.xml index a9ea226808..81f62c4a73 100644 --- a/app/src/main/res/layout/fragment_conversation_bottom_sheet.xml +++ b/app/src/main/res/layout/fragment_conversation_bottom_sheet.xml @@ -75,6 +75,14 @@ android:visibility="gone" /> + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8c4994d5e8..32f3cfa122 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -904,5 +904,6 @@ Would you like to export your application logs to be able to share for troubleshooting? Pin Unpin + Mark all as read diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 0b7ac4c149..1e78c00587 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -78,6 +78,7 @@ @drawable/ic_baseline_info_24 @drawable/ic_outline_pin_24 @drawable/ic_outline_pin_off_24 + @drawable/ic_outline_mark_chat_read_24 @drawable/ic_emoji_filled_keyboard_24 @drawable/ic_sticker_filled_keyboard_24 diff --git a/libsession/src/main/res/values/attrs.xml b/libsession/src/main/res/values/attrs.xml index 9ece70ec1c..558e90799a 100644 --- a/libsession/src/main/res/values/attrs.xml +++ b/libsession/src/main/res/values/attrs.xml @@ -121,6 +121,7 @@ +