Add improved notification settings when muted.

This commit is contained in:
Greyson Parrelli
2026-03-02 13:33:53 -05:00
parent 8a36425cac
commit a95ebb2158
30 changed files with 800 additions and 72 deletions

View File

@@ -13,6 +13,7 @@ import androidx.annotation.WorkerThread;
import org.signal.core.util.CursorUtil;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.RecipientTable;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.signal.core.ui.permissions.Permissions;
import org.thoughtcrime.securesms.recipients.Recipient;
@@ -27,9 +28,31 @@ public final class DoNotDisturbUtil {
private DoNotDisturbUtil() {
}
/**
* Checks whether the user should be disturbed with a call from the given recipient,
* taking into account the recipient's mute and call notification settings as well as
* the system Do Not Disturb state.
*
* For group recipients, only the system interruption filter is checked (no contact priority).
* For 1:1 recipients, the full DND policy including contact priority is evaluated.
*/
@WorkerThread
@SuppressLint("SwitchIntDef")
public static boolean shouldDisturbUserWithCall(@NonNull Context context) {
public static boolean shouldDisturbUserWithCall(@NonNull Context context, @NonNull Recipient recipient) {
if (recipient.isMuted() && recipient.getCallNotificationSetting() == RecipientTable.NotificationSetting.DO_NOT_NOTIFY) {
return false;
}
if (recipient.isGroup()) {
return checkSystemDnd(context);
} else {
return checkSystemDndWithContactPriority(context, recipient);
}
}
@WorkerThread
@SuppressLint("SwitchIntDef")
private static boolean checkSystemDnd(@NonNull Context context) {
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
switch (notificationManager.getCurrentInterruptionFilter()) {
@@ -43,7 +66,7 @@ public final class DoNotDisturbUtil {
@WorkerThread
@SuppressLint("SwitchIntDef")
public static boolean shouldDisturbUserWithCall(@NonNull Context context, @NonNull Recipient recipient) {
private static boolean checkSystemDndWithContactPriority(@NonNull Context context, @NonNull Recipient recipient) {
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
switch (notificationManager.getCurrentInterruptionFilter()) {

View File

@@ -167,13 +167,13 @@ object NotificationStateProvider {
isUnreadMessage &&
!messageRecord.isOutgoing &&
isGroupStoryReply &&
(isParentStorySentBySelf || messageRecord.hasSelfMentionOrQuoteOfSelf() || (hasSelfRepliedToStory && !messageRecord.isStoryReaction()))
(isParentStorySentBySelf || messageRecord.hasGroupQuoteOrSelfMention() || (hasSelfRepliedToStory && !messageRecord.isStoryReaction()))
fun includeMessage(notificationProfile: NotificationProfile?): MessageInclusion {
return if (isUnreadIncoming || stickyThread || isNotifiableGroupStoryMessage || isIncomingMissedCall) {
if (threadRecipient.isMuted && (threadRecipient.isDoNotNotifyMentions || !messageRecord.shouldBreakThroughMute(threadRecipient))) {
if (threadRecipient.isMuted && !breaksThroughMute()) {
MessageInclusion.MUTE_FILTERED
} else if (notificationProfile != null && !notificationProfile.isRecipientAllowed(threadRecipient.id) && !(notificationProfile.allowAllMentions && messageRecord.shouldBreakThroughMute(threadRecipient))) {
} else if (notificationProfile != null && !notificationProfile.isRecipientAllowed(threadRecipient.id) && !(notificationProfile.allowAllMentions && messageRecord.hasGroupQuoteOrSelfMention())) {
MessageInclusion.PROFILE_FILTERED
} else {
MessageInclusion.INCLUDE
@@ -183,6 +183,19 @@ object NotificationStateProvider {
}
}
private fun breaksThroughMute(): Boolean {
return when {
isIncomingMissedCall -> threadRecipient.callNotificationSetting == RecipientTable.NotificationSetting.ALWAYS_NOTIFY
messageRecord.hasSelfMention() -> threadRecipient.mentionSetting == RecipientTable.NotificationSetting.ALWAYS_NOTIFY
messageRecord.isQuoteOfSelf() -> threadRecipient.replyNotificationSetting == RecipientTable.NotificationSetting.ALWAYS_NOTIFY
else -> false
}
}
private fun MessageRecord.isQuoteOfSelf(): Boolean {
return this is MmsMessageRecord && quote?.author == Recipient.self().id
}
fun includeReaction(reaction: ReactionRecord, notificationProfile: NotificationProfile?): MessageInclusion {
return if (threadRecipient.isMuted) {
MessageInclusion.MUTE_FILTERED
@@ -207,19 +220,12 @@ object NotificationStateProvider {
}
}
private val Recipient.isDoNotNotifyMentions: Boolean
get() = mentionSetting == RecipientTable.MentionSetting.DO_NOT_NOTIFY
private fun MessageRecord.shouldBreakThroughMute(threadRecipient: Recipient): Boolean {
private fun MessageRecord.hasGroupQuoteOrSelfMention(): Boolean {
if (!threadRecipient.isGroup) {
return false
}
return hasSelfMention() || (this is MmsMessageRecord && quote?.author == Recipient.self().id)
}
private fun MessageRecord.hasSelfMentionOrQuoteOfSelf(): Boolean {
return hasSelfMention() || (this is MmsMessageRecord && quote?.author == Recipient.self().id)
}
}
private enum class MessageInclusion {