From 600acb82bd1fedda81db8f93c818ff0419e2b01b Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Thu, 25 Jun 2026 11:12:48 -0400 Subject: [PATCH] Move improved notification management to Labs. --- .../components/settings/app/labs/LabsSettingsEvents.kt | 1 + .../components/settings/app/labs/LabsSettingsFragment.kt | 9 +++++++++ .../components/settings/app/labs/LabsSettingsState.kt | 3 ++- .../settings/app/labs/LabsSettingsViewModel.kt | 7 ++++++- .../org/thoughtcrime/securesms/keyvalue/LabsValues.kt | 3 +++ .../org/thoughtcrime/securesms/recipients/Recipient.kt | 5 ++--- 6 files changed, 23 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsEvents.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsEvents.kt index 5d47884b9a..1a06eaef88 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsEvents.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsEvents.kt @@ -12,4 +12,5 @@ sealed interface LabsSettingsEvents { data class ToggleBetterSearch(val enabled: Boolean) : LabsSettingsEvents data class ToggleStarredMessages(val enabled: Boolean) : LabsSettingsEvents data class ToggleStickerReplies(val enabled: Boolean) : LabsSettingsEvents + data class ToggleMuteBreakthroughNotifications(val enabled: Boolean) : LabsSettingsEvents } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsFragment.kt index fe36ff5666..64c29a3cac 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsFragment.kt @@ -142,6 +142,15 @@ private fun LabsSettingsContent( onCheckChanged = { onEvent(LabsSettingsEvents.ToggleStickerReplies(it)) } ) } + + item { + Rows.ToggleRow( + checked = state.muteBreakthroughNotifications, + text = "Improved Notification Management", + label = "Adds per-conversation controls to let calls and replies break through mute. New options in the sounds & notifications settings for a chat.", + onCheckChanged = { onEvent(LabsSettingsEvents.ToggleMuteBreakthroughNotifications(it)) } + ) + } } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsState.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsState.kt index 7fd1613810..9b09af84ca 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsState.kt @@ -14,5 +14,6 @@ data class LabsSettingsState( val incognito: Boolean = false, val betterSearch: Boolean = false, val starredMessages: Boolean = false, - val stickerReplies: Boolean = false + val stickerReplies: Boolean = false, + val muteBreakthroughNotifications: Boolean = false ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsViewModel.kt index 1353037cb5..ce3a62e64c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/labs/LabsSettingsViewModel.kt @@ -41,6 +41,10 @@ class LabsSettingsViewModel : ViewModel() { SignalStore.labs.stickerReplies = event.enabled _state.value = _state.value.copy(stickerReplies = event.enabled) } + is LabsSettingsEvents.ToggleMuteBreakthroughNotifications -> { + SignalStore.labs.muteBreakthroughNotifications = event.enabled + _state.value = _state.value.copy(muteBreakthroughNotifications = event.enabled) + } } } @@ -51,7 +55,8 @@ class LabsSettingsViewModel : ViewModel() { incognito = SignalStore.labs.incognito, betterSearch = SignalStore.labs.betterSearch, starredMessages = SignalStore.labs.starredMessages, - stickerReplies = SignalStore.labs.stickerReplies + stickerReplies = SignalStore.labs.stickerReplies, + muteBreakthroughNotifications = SignalStore.labs.muteBreakthroughNotifications ) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/LabsValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/LabsValues.kt index 2f31cbcafe..8ff1d4ab01 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/LabsValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/LabsValues.kt @@ -10,6 +10,7 @@ class LabsValues internal constructor(store: KeyValueStore) : SignalStoreValues( const val BETTER_SEARCH: String = "labs.better_search" const val STARRED_MESSAGES: String = "labs.starred_messages" const val STICKER_REPLIES: String = "labs.sticker_replies" + const val MUTE_BREAKTHROUGH_NOTIFICATIONS: String = "labs.mute_breakthrough_notifications" } public override fun onFirstEverAppLaunch() = Unit @@ -28,6 +29,8 @@ class LabsValues internal constructor(store: KeyValueStore) : SignalStoreValues( var stickerReplies by booleanValue(STICKER_REPLIES, false).falseForExternalUsers() + var muteBreakthroughNotifications by booleanValue(MUTE_BREAKTHROUGH_NOTIFICATIONS, true).falseForExternalUsers() + private fun SignalStoreValueDelegate.falseForExternalUsers(): SignalStoreValueDelegate { return this.map { actualValue -> RemoteConfig.internalUser && actualValue } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.kt b/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.kt index f4fc8f8b3b..62727fba63 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.kt @@ -51,7 +51,6 @@ import org.thoughtcrime.securesms.phonenumbers.NumberUtil import org.thoughtcrime.securesms.profiles.ProfileName import org.thoughtcrime.securesms.recipients.Recipient.Companion.external import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId -import org.thoughtcrime.securesms.util.RemoteConfig import org.thoughtcrime.securesms.util.SignalE164Util import org.thoughtcrime.securesms.util.SpanUtil import org.thoughtcrime.securesms.util.UsernameUtil.isValidUsernameForSearch @@ -339,11 +338,11 @@ class Recipient( /** Whether calls should break through mute for this recipient. */ val callNotificationSetting: NotificationSetting - get() = if (RemoteConfig.internalUser) callNotificationSettingValue else NotificationSetting.ALWAYS_NOTIFY + get() = if (SignalStore.labs.muteBreakthroughNotifications) callNotificationSettingValue else NotificationSetting.ALWAYS_NOTIFY /** Whether replies should break through mute for this recipient. Only applicable to groups. */ val replyNotificationSetting: NotificationSetting - get() = if (groupIdValue == null) NotificationSetting.DO_NOT_NOTIFY else if (RemoteConfig.internalUser) replyNotificationSettingValue else mentionSetting + get() = if (groupIdValue == null) NotificationSetting.DO_NOT_NOTIFY else if (SignalStore.labs.muteBreakthroughNotifications) replyNotificationSettingValue else mentionSetting /** The state around whether we can send sealed sender to this user. */ val sealedSenderAccessMode: SealedSenderAccessMode = if (pni.isPresent && pni == serviceId) {