Explorar o código

Fix new message notification logic

Previously, the conversation was fetched and passed to `onNewMessage`
before updating it with the new data. This could lead to situations like
notifications being triggered for conversations that were muted since
the last message, since the `isMuted` check would still operate on the
old data.

Additionally, the first message of a new conversation did previously not
trigger a notification at all.
Danilo Bargen %!s(int64=7) %!d(string=hai) anos
pai
achega
dd37435a83
Modificáronse 3 ficheiros con 42 adicións e 19 borrados
  1. 25 19
      src/services/webclient.ts
  2. 1 0
      src/threema.d.ts
  3. 16 0
      src/threema/container.ts

+ 25 - 19
src/services/webclient.ts

@@ -1649,27 +1649,34 @@ export class WebClientService {
                 if (data.unreadCount > 0) {
 
                     // Find the correct conversation in the conversation list
-                    for (let conversation of this.conversations.get()) {
-                        if (this.receiverService.compare(conversation, data)) {
-
-                            if (data.unreadCount > conversation.unreadCount) {
-                                // This is our conversation! If the unreadcount
-                                // has increased, we received a new message.
-                                this.onNewMessage(data.latestMessage, conversation);
-                            } else if (data.unreadCount < conversation.unreadCount) {
-                                // Otherwise, if it has decreased, hide the notification.
-                                this.notificationService.hideNotification(data.type + '-' + data.id);
-                            }
-
-                            break;
+                    const conversation = this.conversations.find(data);
+                    if (data === null) {
+                        // Conversation not found, add it!
+                        this.conversations.add(data);
+                        this.onNewMessage(data.latestMessage, conversation);
+                    } else {
+                        // Check for unread count changes
+                        const unreadCountIncreased = data.unreadCount > conversation.unreadCount;
+                        const unreadCountDecreased = data.unreadCount < conversation.unreadCount;
+
+                        // Update the conversation
+                        this.conversations.updateOrAdd(data);
+
+                        // If the unreadcount has increased, we received a new message.
+                        // Otherwise, if it has decreased, hide the notification.
+                        if (unreadCountIncreased) {
+                            this.onNewMessage(data.latestMessage, conversation);
+                        } else if (unreadCountDecreased) {
+                            this.notificationService.hideNotification(data.type + '-' + data.id);
                         }
                     }
+
                 } else {
+                    // Update the conversation and hide any notifications
+                    this.conversations.updateOrAdd(data);
                     this.notificationService.hideNotification(data.type + '-' + data.id);
                 }
-                // we have to call update or add, we are not sure if this
-                // conversation is already fetched
-                this.conversations.updateOrAdd(data);
+
                 break;
             case WebClientService.ARGUMENT_MODE_REMOVED:
                 this.conversations.remove(data);
@@ -2088,10 +2095,9 @@ export class WebClientService {
      * Called when a new message arrives.
      */
     private onNewMessage(message: threema.Message, conversation: threema.Conversation): void {
-        // ignore message from active receivers (and if the browser tab is visible
+        // Ignore message from active receivers (and if the browser tab is visible)
         if (this.browserService.isVisible()
-            && this.receiverService.compare(conversation, this.receiverService.getActive())) {
-            this.$log.debug('do not show a notification of a active chat');
+                && this.receiverService.compare(conversation, this.receiverService.getActive())) {
             return;
         }
         const sender: threema.Receiver = conversation.receiver;

+ 1 - 0
src/threema.d.ts

@@ -524,6 +524,7 @@ declare namespace threema {
         interface Conversations {
             get(): Conversation[];
             set(data: Conversation[]): void;
+            find(pattern: Conversation | Receiver): Conversation | null;
             add(conversation: Conversation): void;
             updateOrAdd(conversation: Conversation): void;
             remove(conversation: Conversation): void;

+ 16 - 0
src/threema/container.ts

@@ -250,6 +250,22 @@ angular.module('3ema.container', [])
             });
         }
 
+        /**
+         * Find a stored conversation matching the given conversation or receiver.
+         *
+         * Comparison is done by type and id.
+         */
+        public find(pattern: threema.Conversation | threema.Receiver): threema.Conversation | null {
+            for (let conversation of this.get()) {
+                const a = pattern;
+                const b = conversation;
+                if (a !== undefined && b !== undefined && a.type === b.type && a.id === b.id) {
+                    return conversation;
+                }
+            }
+            return null;
+        }
+
         public add(conversation: threema.Conversation): void {
             this.conversations.splice(conversation.position, 0, conversation);
         }