From 90c7c1bf7de3e4e4136a53dde83cb418534213dc Mon Sep 17 00:00:00 2001
From: Claire <claire.github-309c@sitedethib.com>
Date: Thu, 21 Nov 2024 17:10:07 +0100
Subject: [PATCH] Fix duplicate notifications in notification groups when using
 slow mode (#33014)

---
 .../mastodon/models/notification_group.ts     | 32 +++++++++++++++----
 .../mastodon/reducers/notification_groups.ts  | 11 ++++---
 2 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/app/javascript/mastodon/models/notification_group.ts b/app/javascript/mastodon/models/notification_group.ts
index 09d407d449..a76d82503a 100644
--- a/app/javascript/mastodon/models/notification_group.ts
+++ b/app/javascript/mastodon/models/notification_group.ts
@@ -16,6 +16,7 @@ export const NOTIFICATIONS_GROUP_MAX_AVATARS = 8;
 interface BaseNotificationGroup
   extends Omit<BaseNotificationGroupJSON, 'sample_account_ids'> {
   sampleAccountIds: string[];
+  partial: boolean;
 }
 
 interface BaseNotificationWithStatus<Type extends NotificationWithStatusType>
@@ -128,6 +129,7 @@ export function createNotificationGroupFromJSON(
       return {
         statusId: statusId ?? undefined,
         sampleAccountIds,
+        partial: false,
         ...groupWithoutStatus,
       };
     }
@@ -136,12 +138,14 @@ export function createNotificationGroupFromJSON(
       return {
         report: createReportFromJSON(report),
         sampleAccountIds,
+        partial: false,
         ...groupWithoutTargetAccount,
       };
     }
     case 'severed_relationships':
       return {
         ...group,
+        partial: false,
         event: createAccountRelationshipSeveranceEventFromJSON(group.event),
         sampleAccountIds,
       };
@@ -150,13 +154,16 @@ export function createNotificationGroupFromJSON(
       const { moderation_warning, ...groupWithoutModerationWarning } = group;
       return {
         ...groupWithoutModerationWarning,
+        partial: false,
         moderationWarning: createAccountWarningFromJSON(moderation_warning),
         sampleAccountIds,
       };
     }
+
     default:
       return {
         sampleAccountIds,
+        partial: false,
         ...group,
       };
   }
@@ -164,17 +171,17 @@ export function createNotificationGroupFromJSON(
 
 export function createNotificationGroupFromNotificationJSON(
   notification: ApiNotificationJSON,
-) {
+): NotificationGroup {
   const group = {
     sampleAccountIds: [notification.account.id],
     group_key: notification.group_key,
     notifications_count: 1,
-    type: notification.type,
     most_recent_notification_id: notification.id,
     page_min_id: notification.id,
     page_max_id: notification.id,
     latest_page_notification_at: notification.created_at,
-  } as NotificationGroup;
+    partial: true,
+  };
 
   switch (notification.type) {
     case 'favourite':
@@ -183,12 +190,21 @@ export function createNotificationGroupFromNotificationJSON(
     case 'mention':
     case 'poll':
     case 'update':
-      return { ...group, statusId: notification.status?.id };
+      return {
+        ...group,
+        type: notification.type,
+        statusId: notification.status?.id,
+      };
     case 'admin.report':
-      return { ...group, report: createReportFromJSON(notification.report) };
+      return {
+        ...group,
+        type: notification.type,
+        report: createReportFromJSON(notification.report),
+      };
     case 'severed_relationships':
       return {
         ...group,
+        type: notification.type,
         event: createAccountRelationshipSeveranceEventFromJSON(
           notification.event,
         ),
@@ -196,11 +212,15 @@ export function createNotificationGroupFromNotificationJSON(
     case 'moderation_warning':
       return {
         ...group,
+        type: notification.type,
         moderationWarning: createAccountWarningFromJSON(
           notification.moderation_warning,
         ),
       };
     default:
-      return group;
+      return {
+        ...group,
+        type: notification.type,
+      };
   }
 }
diff --git a/app/javascript/mastodon/reducers/notification_groups.ts b/app/javascript/mastodon/reducers/notification_groups.ts
index 7a165f5fec..d43714beb7 100644
--- a/app/javascript/mastodon/reducers/notification_groups.ts
+++ b/app/javascript/mastodon/reducers/notification_groups.ts
@@ -534,10 +534,13 @@ export const notificationGroupsReducer = createReducer<NotificationGroupsState>(
             if (existingGroupIndex > -1) {
               const existingGroup = state.groups[existingGroupIndex];
               if (existingGroup && existingGroup.type !== 'gap') {
-                group.notifications_count += existingGroup.notifications_count;
-                group.sampleAccountIds = group.sampleAccountIds
-                  .concat(existingGroup.sampleAccountIds)
-                  .slice(0, NOTIFICATIONS_GROUP_MAX_AVATARS);
+                if (group.partial) {
+                  group.notifications_count +=
+                    existingGroup.notifications_count;
+                  group.sampleAccountIds = group.sampleAccountIds
+                    .concat(existingGroup.sampleAccountIds)
+                    .slice(0, NOTIFICATIONS_GROUP_MAX_AVATARS);
+                }
                 state.groups.splice(existingGroupIndex, 1);
               }
             }