From ffcb0574ccb0febc32c3f49f3734032f922d9998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Danthinne?= Date: Sat, 28 Jan 2023 09:04:35 +0100 Subject: [PATCH] Fix: consolidated notifications (#461) * Fix consolidated notifications pagination * Only group followers on All notifications screen --- .../NotificationsViewModel.swift | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Packages/Notifications/Sources/Notifications/NotificationsViewModel.swift b/Packages/Notifications/Sources/Notifications/NotificationsViewModel.swift index 4ccb147f..603a1e6a 100644 --- a/Packages/Notifications/Sources/Notifications/NotificationsViewModel.swift +++ b/Packages/Notifications/Sources/Notifications/NotificationsViewModel.swift @@ -65,7 +65,7 @@ class NotificationsViewModel: ObservableObject { maxId: nil, types: queryTypes)) self.notifications = notifications - consolidatedNotifications = notifications.consolidated() + consolidatedNotifications = notifications.consolidated(selectedType: selectedType) nextPageState = notifications.count < 15 ? .none : .hasNextPage } else if let first = consolidatedNotifications.first { var newNotifications: [Models.Notification] = @@ -77,7 +77,10 @@ class NotificationsViewModel: ObservableObject { !consolidatedNotifications.contains(where: { $0.id == notification.id }) } notifications.append(contentsOf: newNotifications) - consolidatedNotifications.insert(contentsOf: newNotifications.consolidated(), at: 0) + consolidatedNotifications.insert( + contentsOf: newNotifications.consolidated(selectedType: selectedType), + at: 0 + ) } withAnimation { state = .display(notifications: consolidatedNotifications, @@ -91,13 +94,13 @@ class NotificationsViewModel: ObservableObject { func fetchNextPage() async { guard let client else { return } do { - guard let lastId = consolidatedNotifications.last?.id else { return } + guard let lastId = consolidatedNotifications.last?.notificationIds.last else { return } state = .display(notifications: consolidatedNotifications, nextPageState: .loadingNextPage) let newNotifications: [Models.Notification] = try await client.get(endpoint: Notifications.notifications(sinceId: nil, maxId: lastId, types: queryTypes)) - consolidatedNotifications.append(contentsOf: newNotifications.consolidated()) + consolidatedNotifications.append(contentsOf: newNotifications.consolidated(selectedType: selectedType)) notifications.append(contentsOf: newNotifications) state = .display(notifications: consolidatedNotifications, nextPageState: newNotifications.count < 15 ? .none : .hasNextPage) } catch { @@ -118,10 +121,10 @@ class NotificationsViewModel: ObservableObject { { if let selectedType, event.notification.type == selectedType.rawValue { notifications.insert(event.notification, at: 0) - consolidatedNotifications = notifications.consolidated() + consolidatedNotifications = notifications.consolidated(selectedType: selectedType) } else if selectedType == nil { notifications.insert(event.notification, at: 0) - consolidatedNotifications = notifications.consolidated() + consolidatedNotifications = notifications.consolidated(selectedType: selectedType) } state = .display(notifications: consolidatedNotifications, nextPageState: .hasNextPage) } @@ -129,14 +132,16 @@ class NotificationsViewModel: ObservableObject { } struct ConsolidatedNotification: Identifiable { - let id: String + let notificationIds: [String] let type: Models.Notification.NotificationType let createdAt: ServerDate let accounts: [Account] let status: Status? + var id: String? { notificationIds.first } + static func placeholder() -> ConsolidatedNotification { - .init(id: UUID().uuidString, + .init(notificationIds: [UUID().uuidString], type: .favourite, createdAt: "2022-12-16T10:20:54.000Z", accounts: [.placeholder()], @@ -149,19 +154,19 @@ struct ConsolidatedNotification: Identifiable { } extension Array where Element == Models.Notification { - func consolidated() -> [ConsolidatedNotification] { + func consolidated(selectedType: Models.Notification.NotificationType?) -> [ConsolidatedNotification] { Dictionary(grouping: self) { notification -> String? in guard let supportedType = notification.supportedType else { return nil } switch supportedType { - case .follow: + case .follow where selectedType != .follow: // Always group followers return supportedType.rawValue case .reblog, .favourite: // Group boosts and favourites by status return "\(supportedType.rawValue)-\(notification.status?.id ?? "")" - case .follow_request, .poll, .status, .update, .mention: - // Never group those + default: + // Never group remaining ones return notification.id } } @@ -171,7 +176,7 @@ extension Array where Element == Models.Notification { let supportedType = notification.supportedType else { return nil } - return ConsolidatedNotification(id: notification.id, + return ConsolidatedNotification(notificationIds: notifications.map(\.id), type: supportedType, createdAt: notification.createdAt, accounts: notifications.map(\.account),