Improve mention notifications by only showing alerting notifications once.

This commit is contained in:
Cody Henthorne
2020-11-11 14:49:48 -05:00
parent 3bb366ee04
commit 696fffb603
13 changed files with 118 additions and 42 deletions

View File

@@ -39,6 +39,8 @@ import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.contactshare.ContactUtil;
@@ -71,6 +73,7 @@ import org.thoughtcrime.securesms.webrtc.CallNotificationBuilder;
import org.whispersystems.signalservice.internal.util.Util;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
@@ -281,8 +284,9 @@ public class DefaultMessageNotifier implements MessageNotifier {
boolean signal,
int reminderCount)
{
Cursor telcoCursor = null;
Cursor pushCursor = null;
boolean isReminder = reminderCount > 0;
Cursor telcoCursor = null;
Cursor pushCursor = null;
try {
telcoCursor = DatabaseFactory.getMmsSmsDatabase(context).getUnread();
@@ -305,6 +309,8 @@ public class DefaultMessageNotifier implements MessageNotifier {
lastAudibleNotification = System.currentTimeMillis();
}
boolean shouldScheduleReminder = signal;
if (notificationState.hasMultipleThreads()) {
if (Build.VERSION.SDK_INT >= 23) {
for (long threadId : notificationState.getThreads()) {
@@ -312,14 +318,15 @@ public class DefaultMessageNotifier implements MessageNotifier {
sendSingleThreadNotification(context,
new NotificationState(notificationState.getNotificationsForThread(threadId)),
signal && (threadId == targetThread),
true);
true,
isReminder);
}
}
}
sendMultipleThreadNotification(context, notificationState, signal && (Build.VERSION.SDK_INT < 23));
} else {
sendSingleThreadNotification(context, notificationState, signal, false);
shouldScheduleReminder = sendSingleThreadNotification(context, notificationState, signal, false, isReminder);
if (isDisplayingSummaryNotification(context)) {
sendMultipleThreadNotification(context, notificationState, false);
@@ -329,7 +336,18 @@ public class DefaultMessageNotifier implements MessageNotifier {
cancelOrphanedNotifications(context, notificationState);
updateBadge(context, notificationState.getMessageCount());
if (signal) {
List<Long> smsIds = new LinkedList<>();
List<Long> mmsIds = new LinkedList<>();
for (NotificationItem item : notificationState.getNotifications()) {
if (item.isMms()) {
mmsIds.add(item.getId());
} else {
smsIds.add(item.getId());
}
}
DatabaseFactory.getMmsSmsDatabase(context).setNotifiedTimestamp(System.currentTimeMillis(), smsIds, mmsIds);
if (shouldScheduleReminder) {
scheduleReminder(context, reminderCount);
}
} finally {
@@ -338,23 +356,25 @@ public class DefaultMessageNotifier implements MessageNotifier {
}
}
private static void sendSingleThreadNotification(@NonNull Context context,
@NonNull NotificationState notificationState,
boolean signal,
boolean bundled)
private static boolean sendSingleThreadNotification(@NonNull Context context,
@NonNull NotificationState notificationState,
boolean signal,
boolean bundled,
boolean isReminder)
{
Log.i(TAG, "sendSingleThreadNotification() signal: " + signal + " bundled: " + bundled);
if (notificationState.getNotifications().isEmpty()) {
if (!bundled) cancelActiveNotifications(context);
Log.i(TAG, "[sendSingleThreadNotification] Empty notification state. Skipping.");
return;
return false;
}
NotificationPrivacyPreference notificationPrivacy = TextSecurePreferences.getNotificationPrivacy(context);
SingleRecipientNotificationBuilder builder = new SingleRecipientNotificationBuilder(context, notificationPrivacy);
List<NotificationItem> notifications = notificationState.getNotifications();
Recipient recipient = notifications.get(0).getRecipient();
boolean shouldAlert = signal && (isReminder || Stream.of(notifications).anyMatch(item -> item.getNotifiedTimestamp() == 0));
int notificationId;
if (Build.VERSION.SDK_INT >= 23) {
@@ -369,7 +389,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
notifications.get(0).getText(), notifications.get(0).getSlideDeck());
builder.setContentIntent(notifications.get(0).getPendingIntent(context));
builder.setDeleteIntent(notificationState.getDeleteIntent(context));
builder.setOnlyAlertOnce(!signal);
builder.setOnlyAlertOnce(!shouldAlert);
builder.setSortKey(String.valueOf(Long.MAX_VALUE - notifications.get(0).getTimestamp()));
long timestamp = notifications.get(0).getTimestamp();
@@ -418,6 +438,8 @@ public class DefaultMessageNotifier implements MessageNotifier {
Notification notification = builder.build();
NotificationManagerCompat.from(context).notify(notificationId, notification);
Log.i(TAG, "Posted notification.");
return shouldAlert;
}
private static void sendMultipleThreadNotification(@NonNull Context context,
@@ -434,11 +456,12 @@ public class DefaultMessageNotifier implements MessageNotifier {
NotificationPrivacyPreference notificationPrivacy = TextSecurePreferences.getNotificationPrivacy(context);
MultipleRecipientNotificationBuilder builder = new MultipleRecipientNotificationBuilder(context, notificationPrivacy);
List<NotificationItem> notifications = notificationState.getNotifications();
boolean shouldAlert = signal && Stream.of(notifications).anyMatch(item -> item.getNotifiedTimestamp() == 0);
builder.setMessageCount(notificationState.getMessageCount(), notificationState.getThreadCount());
builder.setMostRecentSender(notifications.get(0).getIndividualRecipient());
builder.setDeleteIntent(notificationState.getDeleteIntent(context));
builder.setOnlyAlertOnce(!signal);
builder.setOnlyAlertOnce(!shouldAlert);
if (Build.VERSION.SDK_INT >= 23) {
builder.setGroup(NOTIFICATION_GROUP);
@@ -531,6 +554,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
boolean isUnreadMessage = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsColumns.READ)) == 0;
boolean hasUnreadReactions = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsColumns.REACTIONS_UNREAD)) == 1;
long lastReactionRead = cursor.getLong(cursor.getColumnIndexOrThrow(MmsSmsColumns.REACTIONS_LAST_SEEN));
long notifiedTimestamp = record.getNotifiedTimestamp();
if (threadId != -1) {
threadRecipients = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
@@ -564,7 +588,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
}
if (threadRecipients == null || includeMessage) {
notificationState.addNotification(new NotificationItem(id, mms, recipient, conversationRecipient, threadRecipients, threadId, body, timestamp, receivedTimestamp, slideDeck, false, record.isJoined(), canReply));
notificationState.addNotification(new NotificationItem(id, mms, recipient, conversationRecipient, threadRecipients, threadId, body, timestamp, receivedTimestamp, slideDeck, false, record.isJoined(), canReply, notifiedTimestamp));
}
}
@@ -599,7 +623,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
}
if (threadRecipients == null || !threadRecipients.isMuted()) {
notificationState.addNotification(new NotificationItem(id, mms, reactionSender, conversationRecipient, threadRecipients, threadId, body, reaction.getDateReceived(), receivedTimestamp, null, true, record.isJoined(), false));
notificationState.addNotification(new NotificationItem(id, mms, reactionSender, conversationRecipient, threadRecipients, threadId, body, reaction.getDateReceived(), receivedTimestamp, null, true, record.isJoined(), false, 0));
}
}
}

View File

@@ -23,12 +23,13 @@ public class NotificationItem {
@Nullable private final Recipient threadRecipient;
private final long threadId;
@Nullable private final CharSequence text;
private final long notificationTimestamp;
private final long timestamp;
private final long messageReceivedTimestamp;
@Nullable private final SlideDeck slideDeck;
private final boolean jumpToMessage;
private final boolean isJoin;
private final boolean canReply;
private final long notifiedTimestamp;
public NotificationItem(long id,
boolean mms,
@@ -37,12 +38,13 @@ public class NotificationItem {
@Nullable Recipient threadRecipient,
long threadId,
@Nullable CharSequence text,
long notificationTimestamp,
long timestamp,
long messageReceivedTimestamp,
@Nullable SlideDeck slideDeck,
boolean jumpToMessage,
boolean isJoin,
boolean canReply)
boolean canReply,
long notifiedTimestamp)
{
this.id = id;
this.mms = mms;
@@ -51,12 +53,13 @@ public class NotificationItem {
this.threadRecipient = threadRecipient;
this.text = text;
this.threadId = threadId;
this.notificationTimestamp = notificationTimestamp;
this.timestamp = timestamp;
this.messageReceivedTimestamp = messageReceivedTimestamp;
this.slideDeck = slideDeck;
this.jumpToMessage = jumpToMessage;
this.isJoin = isJoin;
this.canReply = canReply;
this.notifiedTimestamp = notifiedTimestamp;
}
public @NonNull Recipient getRecipient() {
@@ -72,7 +75,7 @@ public class NotificationItem {
}
public long getTimestamp() {
return notificationTimestamp;
return timestamp;
}
public long getThreadId() {
@@ -119,4 +122,8 @@ public class NotificationItem {
public boolean canReply() {
return canReply;
}
public long getNotifiedTimestamp() {
return notifiedTimestamp;
}
}