FIX: Maintain order when updating notifications (#13643)

FIX: Maintain order when updating notifications (#13643)

A more complex algorithm was used to achieve consensus between server and client lists of notifications. This commit uses a different and more simple approach that ignores order, but updates read status of existing notifications and removes stale notifications.

diff --git a/app/assets/javascripts/discourse/app/initializers/subscribe-user-notifications.js b/app/assets/javascripts/discourse/app/initializers/subscribe-user-notifications.js
index 52895fd..2381e08 100644
--- a/app/assets/javascripts/discourse/app/initializers/subscribe-user-notifications.js
+++ b/app/assets/javascripts/discourse/app/initializers/subscribe-user-notifications.js
@@ -92,24 +92,17 @@ export default {
               );
             }
 
-            for (let idx = 0; idx < data.recent.length; idx++) {
-              let old;
-              while ((old = oldNotifications[idx])) {
-                const info = data.recent[idx];
-
-                if (old.get("id") !== info[0]) {
-                  oldNotifications.removeAt(idx);
-                } else {
-                  if (old.get("read") !== info[1]) {
-                    old.set("read", info[1]);
-                  }
-                  break;
+            // remove stale notifications and update existing ones
+            const read = Object.fromEntries(data.recent);
+            const newNotifications = oldNotifications
+              .map((notification) => {
+                if (read[notification.id] !== undefined) {
+                  notification.set("read", read[notification.id]);
+                  return notification;
                 }
-              }
-              if (!old) {
-                break;
-              }
-            }
+              })
+              .filter(Boolean);
+            stale.results.set("content", newNotifications);
           }
         },
         user.notification_channel_position
diff --git a/app/assets/javascripts/discourse/tests/acceptance/notifications-test.js b/app/assets/javascripts/discourse/tests/acceptance/notifications-test.js
index 200b290..674f532 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/notifications-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/notifications-test.js
@@ -136,5 +136,65 @@ acceptance("User Notifications", function (needs) {
         .innerText,
       "Second notification"
     );
+
+    // updates existing notifications
+
+    publishToMessageBus("/notification/19", {
+      unread_notifications: 8,
+      unread_private_messages: 0,
+      unread_high_priority_notifications: 1,
+      read_first_notification: false,
+      last_notification: {
+        notification: {
+          id: 44,
+          user_id: 1,
+          notification_type: 5,
+          high_priority: true,
+          read: true,
+          high_priority: false,
+          created_at: "2021-01-01 12:00:00 UTC",
+          post_number: 1,
+          topic_id: 42,
+          fancy_title: "Third notification",
+          slug: "topic",
+          data: {
+            topic_title: "Third notification",
+            original_post_id: 42,
+            original_post_type: 1,
+            original_username: "foo",
+            revision_number: null,
+            display_username: "foo",
+          },
+        },
+      },
+      recent: [
+        [5678, false],
+        [1234, false],
+        [789, false],
+        [456, true],
+        [123, true],
+        [44, false],
+        [43, false],
+        [42, true],
+      ],
+      seen_notification_id: null,
+    });
+
+    await visit("/"); // wait for re-render
+    assert.equal(count("#quick-access-notifications li"), 8);
+    const texts = [];
+    queryAll("#quick-access-notifications li").each((_, el) =>
+      texts.push(el.innerText.trim())
+    );
+    assert.deepEqual(texts, [
+      "foo First notification",
+      "foo Third notification",
+      "foo Second notification",
+      "velesin some title",
+      "aquaman liked 5 of your posts",
+      "5 messages in your test inbox",
+      "test1 accepted your invitation",
+      "Membership accepted in 'test'",
+    ]);
   });
 });

GitHub sha: da03a3f5d61a4bc62475d25ee8730eb9d00d9023

This commit appears in #13643 which was approved by CvX. It was merged by udan11.