diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/OptimizedMessageNotifier.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/OptimizedMessageNotifier.java index f452f4fe7a..1c87f418d0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/OptimizedMessageNotifier.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/OptimizedMessageNotifier.java @@ -11,6 +11,7 @@ import androidx.annotation.Nullable; import org.signal.core.util.ExceptionUtil; import org.signal.core.util.ThreadUtil; import org.signal.core.util.concurrent.SignalExecutors; +import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.notifications.v2.DefaultMessageNotifier; import org.thoughtcrime.securesms.notifications.v2.ConversationId; import org.thoughtcrime.securesms.recipients.Recipient; @@ -27,6 +28,10 @@ public class OptimizedMessageNotifier implements MessageNotifier { private final LeakyBucketLimiter limiter; private final DefaultMessageNotifier defaultMessageNotifier; + private static final String DEDUPE_KEY_GENERAL = "MESSAGE_NOTIFIER_DEFAULT"; + private static final String DEDUPE_KEY_CHAT = "MESSAGE_NOTIFIER_CHAT_"; + private static final String DEDUPE_KEY_CANCEL_DELAYED = "MESSAGE_NOTIFIER_CANCEL_DELAYED"; + @MainThread public OptimizedMessageNotifier(@NonNull Application context) { this.limiter = new LeakyBucketLimiter(3, 1000, new Handler(SignalExecutors.getAndStartHandlerThread("signal-notifier", ThreadUtil.PRIORITY_IMPORTANT_BACKGROUND_THREAD).getLooper())); @@ -55,62 +60,86 @@ public class OptimizedMessageNotifier implements MessageNotifier { @Override public void notifyMessageDeliveryFailed(@NonNull Context context, @NonNull Recipient recipient, @NonNull ConversationId conversationId) { - getNotifier().notifyMessageDeliveryFailed(context, recipient, conversationId); + SignalDatabase.runPostSuccessfulTransaction(() -> { + getNotifier().notifyMessageDeliveryFailed(context, recipient, conversationId); + }); } @Override - public void notifyStoryDeliveryFailed(@NonNull Context context, @NonNull Recipient recipient, @NonNull ConversationId threadId) { - getNotifier().notifyStoryDeliveryFailed(context, recipient, threadId); + public void notifyStoryDeliveryFailed(@NonNull Context context, @NonNull Recipient recipient, @NonNull ConversationId conversationId) { + SignalDatabase.runPostSuccessfulTransaction(() -> { + getNotifier().notifyStoryDeliveryFailed(context, recipient, conversationId); + }); } @Override public void notifyProofRequired(@NonNull Context context, @NonNull Recipient recipient, @NonNull ConversationId conversationId) { - getNotifier().notifyProofRequired(context, recipient, conversationId); + SignalDatabase.runPostSuccessfulTransaction(() -> { + getNotifier().notifyProofRequired(context, recipient, conversationId); + }); } @Override public void cancelDelayedNotifications() { - getNotifier().cancelDelayedNotifications(); + SignalDatabase.runPostSuccessfulTransaction(DEDUPE_KEY_CANCEL_DELAYED, () -> { + getNotifier().cancelDelayedNotifications(); + }); } @Override public void updateNotification(@NonNull Context context) { - runOnLimiter(() -> getNotifier().updateNotification(context)); + SignalDatabase.runPostSuccessfulTransaction(DEDUPE_KEY_GENERAL, () -> { + runOnLimiter(() -> getNotifier().updateNotification(context)); + }); } @Override public void updateNotification(@NonNull Context context, @NonNull ConversationId conversationId) { - runOnLimiter(() -> getNotifier().updateNotification(context, conversationId)); + SignalDatabase.runPostSuccessfulTransaction(DEDUPE_KEY_CHAT + conversationId.getThreadId(), () -> { + runOnLimiter(() -> getNotifier().updateNotification(context, conversationId)); + }); } @Override public void updateNotification(@NonNull Context context, @NonNull ConversationId conversationId, @NonNull BubbleUtil.BubbleState defaultBubbleState) { - runOnLimiter(() -> getNotifier().updateNotification(context, conversationId, defaultBubbleState)); + SignalDatabase.runPostSuccessfulTransaction(() -> { + runOnLimiter(() -> getNotifier().updateNotification(context, conversationId, defaultBubbleState)); + }); } @Override public void updateNotification(@NonNull Context context, @NonNull ConversationId conversationId, boolean signal) { - runOnLimiter(() -> getNotifier().updateNotification(context, conversationId, signal)); + SignalDatabase.runPostSuccessfulTransaction(() -> { + runOnLimiter(() -> getNotifier().updateNotification(context, conversationId, signal)); + }); } @Override public void updateNotification(@NonNull Context context, @Nullable ConversationId conversationId, boolean signal, int reminderCount, @NonNull BubbleUtil.BubbleState defaultBubbleState) { - runOnLimiter(() -> getNotifier().updateNotification(context, conversationId, signal, reminderCount, defaultBubbleState)); + SignalDatabase.runPostSuccessfulTransaction(() -> { + runOnLimiter(() -> getNotifier().updateNotification(context, conversationId, signal, reminderCount, defaultBubbleState)); + }); } @Override public void clearReminder(@NonNull Context context) { - getNotifier().clearReminder(context); + SignalDatabase.runPostSuccessfulTransaction(() -> { + getNotifier().clearReminder(context); + }); } @Override public void addStickyThread(@NonNull ConversationId conversationId, long earliestTimestamp) { - getNotifier().addStickyThread(conversationId, earliestTimestamp); + SignalDatabase.runPostSuccessfulTransaction(() -> { + getNotifier().addStickyThread(conversationId, earliestTimestamp); + }); } @Override public void removeStickyThread(@NonNull ConversationId conversationId) { - getNotifier().removeStickyThread(conversationId); + SignalDatabase.runPostSuccessfulTransaction(() -> { + getNotifier().removeStickyThread(conversationId); + }); } private void runOnLimiter(@NonNull Runnable runnable) {