diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsFragment.kt index 1217eba5c..4fcd2b620 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsFragment.kt @@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.components.settings.configure import org.thoughtcrime.securesms.exporter.flow.SmsExportActivity import org.thoughtcrime.securesms.exporter.flow.SmsExportDialogs import org.thoughtcrime.securesms.keyvalue.SignalStore +import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter import org.thoughtcrime.securesms.util.navigation.safeNavigate @@ -103,6 +104,17 @@ class ChatsSettingsFragment : DSLSettingsFragment(R.string.preferences_chats__ch } ) + if (FeatureFlags.keepMutedChatsArchived() || FeatureFlags.internalUser()) { + switchPref( + title = DSLSettingsText.from(R.string.preferences__pref_keep_muted_chats_archived), + summary = DSLSettingsText.from(R.string.preferences__muted_chats_that_are_archived_will_remain_archived), + isChecked = state.keepMutedChatsArchived, + onClick = { + viewModel.setKeepMutedChatsArchived(!state.keepMutedChatsArchived) + } + ) + } + dividerPref() sectionHeaderPref(R.string.ChatsSettingsFragment__keyboard) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsRepository.kt index 6d2e50e6a..3378ba14c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsRepository.kt @@ -39,4 +39,11 @@ class ChatsSettingsRepository { StorageSyncHelper.scheduleSyncForDataChange() } } + + fun syncKeepMutedChatsArchivedState() { + SignalExecutors.BOUNDED.execute { + SignalDatabase.recipients.markNeedsSync(Recipient.self().id) + StorageSyncHelper.scheduleSyncForDataChange() + } + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsState.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsState.kt index bcb1de842..7c4bfe7c7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsState.kt @@ -5,6 +5,7 @@ import org.thoughtcrime.securesms.components.settings.app.chats.sms.SmsExportSta data class ChatsSettingsState( val generateLinkPreviews: Boolean, val useAddressBook: Boolean, + val keepMutedChatsArchived: Boolean, val useSystemEmoji: Boolean, val enterKeySends: Boolean, val chatBackupsEnabled: Boolean, diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsViewModel.kt index 90f84256c..f54d15874 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/ChatsSettingsViewModel.kt @@ -25,6 +25,7 @@ class ChatsSettingsViewModel @JvmOverloads constructor( ChatsSettingsState( generateLinkPreviews = SignalStore.settings().isLinkPreviewsEnabled, useAddressBook = SignalStore.settings().isPreferSystemContactPhotos, + keepMutedChatsArchived = SignalStore.settings().shouldKeepMutedChatsArchived(), useSystemEmoji = SignalStore.settings().isPreferSystemEmoji, enterKeySends = SignalStore.settings().isEnterKeySends, chatBackupsEnabled = SignalStore.settings().isBackupEnabled && BackupUtil.canUserAccessBackupDirectory(ApplicationDependencies.getApplication()), @@ -57,6 +58,12 @@ class ChatsSettingsViewModel @JvmOverloads constructor( repository.syncPreferSystemContactPhotos() } + fun setKeepMutedChatsArchived(enabled: Boolean) { + store.update { it.copy(keepMutedChatsArchived = enabled) } + SignalStore.settings().setKeepMutedChatsArchived(enabled) + repository.syncKeepMutedChatsArchivedState() + } + fun setUseSystemEmoji(enabled: Boolean) { store.update { it.copy(useSystemEmoji = enabled) } SignalStore.settings().isPreferSystemEmoji = enabled 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 7d10528f4..c0f5f458c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -1979,24 +1979,26 @@ public class MmsDatabase extends MessageDatabase { return Optional.empty(); } - boolean updateThread = retrieved.getStoryType() == StoryType.NONE; - long messageId = insertMediaMessage(threadId, - retrieved.getBody(), - retrieved.getAttachments(), - quoteAttachments, - retrieved.getSharedContacts(), - retrieved.getLinkPreviews(), - retrieved.getMentions(), - retrieved.getMessageRanges(), - contentValues, - null, - updateThread); + boolean updateThread = retrieved.getStoryType() == StoryType.NONE; + boolean keepThreadArchived = SignalStore.settings().shouldKeepMutedChatsArchived() && Recipient.resolved(retrieved.getFrom()).isMuted(); + long messageId = insertMediaMessage(threadId, + retrieved.getBody(), + retrieved.getAttachments(), + quoteAttachments, + retrieved.getSharedContacts(), + retrieved.getLinkPreviews(), + retrieved.getMentions(), + retrieved.getMessageRanges(), + contentValues, + null, + updateThread, + !keepThreadArchived); boolean isNotStoryGroupReply = retrieved.getParentStoryId() == null || !retrieved.getParentStoryId().isGroupReply(); if (!Types.isPaymentsActivated(mailbox) && !Types.isRequestToActivatePayments(mailbox) && !Types.isExpirationTimerUpdate(mailbox) && !retrieved.getStoryType().isStory() && isNotStoryGroupReply) { 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); + SignalDatabase.threads().update(threadId, !keepThreadArchived); } notifyConversationListeners(threadId); @@ -2297,7 +2299,7 @@ public class MmsDatabase extends MessageDatabase { MentionUtil.UpdatedBodyAndMentions updatedBodyAndMentions = MentionUtil.updateBodyAndMentionsWithPlaceholders(message.getBody(), message.getMentions()); - long messageId = insertMediaMessage(threadId, updatedBodyAndMentions.getBodyAsString(), message.getAttachments(), quoteAttachments, message.getSharedContacts(), message.getLinkPreviews(), updatedBodyAndMentions.getMentions(), null, contentValues, insertListener, false); + long messageId = insertMediaMessage(threadId, updatedBodyAndMentions.getBodyAsString(), message.getAttachments(), quoteAttachments, message.getSharedContacts(), message.getLinkPreviews(), updatedBodyAndMentions.getMentions(), null, contentValues, insertListener, false, false); if (message.getRecipient().isGroup()) { OutgoingGroupUpdateMessage outgoingGroupUpdateMessage = (message instanceof OutgoingGroupUpdateMessage) ? (OutgoingGroupUpdateMessage) message : null; @@ -2371,7 +2373,8 @@ public class MmsDatabase extends MessageDatabase { @Nullable BodyRangeList messageRanges, @NonNull ContentValues contentValues, @Nullable InsertListener insertListener, - boolean updateThread) + boolean updateThread, + boolean unarchive) throws MmsException { SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); @@ -2443,7 +2446,7 @@ public class MmsDatabase extends MessageDatabase { if (updateThread) { SignalDatabase.threads().setLastScrolled(contentValuesThreadId, 0); - SignalDatabase.threads().update(threadId, true); + SignalDatabase.threads().update(threadId, unarchive); } } } 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 c22bd0ddb..1b954585d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -742,8 +742,8 @@ public class SmsDatabase extends MessageDatabase { SignalDatabase.threads().incrementUnread(threadId, 1, 0); } - - SignalDatabase.threads().update(threadId, true); + boolean keepThreadArchived = SignalStore.settings().shouldKeepMutedChatsArchived() && recipient.isMuted(); + SignalDatabase.threads().update(threadId, !keepThreadArchived); db.setTransactionSuccessful(); } finally { @@ -820,7 +820,8 @@ public class SmsDatabase extends MessageDatabase { SignalDatabase.threads().incrementUnread(threadId, 1, 0); } - SignalDatabase.threads().update(threadId, true); + final boolean keepThreadArchived = SignalStore.settings().shouldKeepMutedChatsArchived() && recipient.isMuted(); + SignalDatabase.threads().update(threadId, !keepThreadArchived); db.setTransactionSuccessful(); } finally { @@ -891,8 +892,8 @@ public class SmsDatabase extends MessageDatabase { if (unread) { SignalDatabase.threads().incrementUnread(threadId, 1, 0); } - - SignalDatabase.threads().update(threadId, true); + boolean keepThreadArchived = SignalStore.settings().shouldKeepMutedChatsArchived() && Recipient.resolved(recipientId).isMuted(); + SignalDatabase.threads().update(threadId, !keepThreadArchived); notifyConversationListeners(threadId); TrimThreadJob.enqueueAsync(threadId); @@ -1281,7 +1282,8 @@ public class SmsDatabase extends MessageDatabase { } if (!silent) { - SignalDatabase.threads().update(threadId, true); + final boolean keepThreadArchived = SignalStore.settings().shouldKeepMutedChatsArchived() && recipient.isMuted(); + SignalDatabase.threads().update(threadId, !keepThreadArchived); } if (message.getSubscriptionId() != -1) { @@ -1324,7 +1326,8 @@ public class SmsDatabase extends MessageDatabase { long messageId = db.insert(TABLE_NAME, null, values); SignalDatabase.threads().incrementUnread(threadId, 1, 0); - SignalDatabase.threads().update(threadId, true); + boolean keepThreadArchived = SignalStore.settings().shouldKeepMutedChatsArchived() && Recipient.resolved(recipientId).isMuted(); + SignalDatabase.threads().update(threadId, !keepThreadArchived); notifyConversationListeners(threadId); @@ -1348,7 +1351,8 @@ public class SmsDatabase extends MessageDatabase { databaseHelper.getSignalWritableDatabase().insert(TABLE_NAME, null, values); SignalDatabase.threads().incrementUnread(threadId, 1, 0); - SignalDatabase.threads().update(threadId, true); + boolean keepThreadArchived = SignalStore.settings().shouldKeepMutedChatsArchived() && Recipient.resolved(recipientId).isMuted(); + SignalDatabase.threads().update(threadId, !keepThreadArchived); notifyConversationListeners(threadId); diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java index 8a2daa1d8..d8d1084c5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java @@ -105,6 +105,7 @@ public final class FeatureFlags { private static final String SMS_EXPORT_MEGAPHONE_DELAY_DAYS = "android.smsExport.megaphoneDelayDays.2"; public static final String CREDIT_CARD_PAYMENTS = "android.credit.card.payments"; private static final String PAYMENTS_REQUEST_ACTIVATE_FLOW = "android.payments.requestActivateFlow"; + private static final String KEEP_MUTED_CHATS_ARCHIVED = "android.keepMutedChatsArchived"; /** * We will only store remote values for flags in this set. If you want a flag to be controllable @@ -161,7 +162,8 @@ public final class FeatureFlags { HIDE_CONTACTS, SMS_EXPORT_MEGAPHONE_DELAY_DAYS, CREDIT_CARD_PAYMENTS, - PAYMENTS_REQUEST_ACTIVATE_FLOW + PAYMENTS_REQUEST_ACTIVATE_FLOW, + KEEP_MUTED_CHATS_ARCHIVED ); @VisibleForTesting @@ -225,7 +227,8 @@ public final class FeatureFlags { STORIES, SMS_EXPORT_MEGAPHONE_DELAY_DAYS, CREDIT_CARD_PAYMENTS, - PAYMENTS_REQUEST_ACTIVATE_FLOW + PAYMENTS_REQUEST_ACTIVATE_FLOW, + KEEP_MUTED_CHATS_ARCHIVED ); /** @@ -578,6 +581,13 @@ public final class FeatureFlags { return getBoolean(PAYMENTS_REQUEST_ACTIVATE_FLOW, false); } + /** + * Whether users can enable keeping conversations with incoming messages archived if the conversation is muted. + */ + public static boolean keepMutedChatsArchived() { + return getBoolean(KEEP_MUTED_CHATS_ARCHIVED, false); + } + /** Only for rendering debug info. */ public static synchronized @NonNull Map getMemoryValues() { return new TreeMap<>(REMOTE_VALUES); diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/IdentityUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/IdentityUtil.java index bfe554e56..38c0987ad 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/IdentityUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/IdentityUtil.java @@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.database.MessageDatabase.InsertResult; import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.model.IdentityRecord; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; +import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.notifications.v2.ConversationId; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; @@ -112,7 +113,8 @@ public final class IdentityUtil { Log.i(TAG, "Inserting verified outbox..."); SignalDatabase.sms().insertMessageOutbox(threadId, outgoing, false, time, null); - SignalDatabase.threads().update(threadId, true); + boolean keepThreadArchived = SignalStore.settings().shouldKeepMutedChatsArchived() && recipient.isMuted(); + SignalDatabase.threads().update(threadId, !keepThreadArchived); } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0da07af32..96599a797 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2664,6 +2664,10 @@ Pressing the Enter key will send text messages Use address book photos Display contact photos from your address book if available + + Keep Muted Chats Archived + + Muted chats that are archived will remain archived when a new message arrives. Generate link previews Retrieve link previews directly from websites for messages you send. Choose identity