diff --git a/Tusker/Screens/Notifications/NotificationsTableViewController.swift b/Tusker/Screens/Notifications/NotificationsTableViewController.swift index 0343a369..f39364b1 100644 --- a/Tusker/Screens/Notifications/NotificationsTableViewController.swift +++ b/Tusker/Screens/Notifications/NotificationsTableViewController.swift @@ -8,6 +8,7 @@ import UIKit import Pachyderm +import Sentry class NotificationsTableViewController: DiffableTimelineLikeTableViewController { @@ -71,7 +72,18 @@ class NotificationsTableViewController: DiffableTimelineLikeTableViewController< fatalError() } cell.delegate = self - cell.updateUI(statusID: notification.status!.id, state: group.statusState!) + guard let status = notification.status else { + let crumb = Breadcrumb(level: .fatal, category: "notifications") + crumb.data = [ + "id": notification.id, + "type": notification.kind.rawValue, + "created_at": notification.createdAt.formatted(.iso8601), + "account": notification.account.id, + ] + SentrySDK.addBreadcrumb(crumb: crumb) + fatalError("missing status for mention notification") + } + cell.updateUI(statusID: status.id, state: group.statusState!) return cell case .favourite, .reblog: @@ -114,6 +126,19 @@ class NotificationsTableViewController: DiffableTimelineLikeTableViewController< } } + private func validateNotifications(_ notifications: [Pachyderm.Notification]) { + for notif in notifications where notif.status == nil && (notif.kind == .mention || notif.kind == .reblog || notif.kind == .favourite) { + let crumb = Breadcrumb(level: .fatal, category: "notifications") + crumb.data = [ + "id": notif.id, + "type": notif.kind.rawValue, + "created_at": notif.createdAt.formatted(.iso8601), + "account": notif.account.id, + ] + SentrySDK.addBreadcrumb(crumb: crumb) + } + } + override func loadInitialItems(completion: @escaping (LoadResult) -> Void) { let request = Client.getNotifications(excludeTypes: excludedTypes) mastodonController.run(request) { (response) in @@ -122,6 +147,7 @@ class NotificationsTableViewController: DiffableTimelineLikeTableViewController< completion(.failure(.client(error))) case let .success(notifications, _): + self.validateNotifications(notifications) let groups = NotificationGroup.createGroups(notifications: notifications, only: self.groupTypes) if !notifications.isEmpty { @@ -152,6 +178,7 @@ class NotificationsTableViewController: DiffableTimelineLikeTableViewController< completion(.failure(.client(error))) case let .success(newNotifications, _): + self.validateNotifications(newNotifications) if !newNotifications.isEmpty { self.older = .before(id: newNotifications.last!.id, count: nil) } @@ -183,6 +210,7 @@ class NotificationsTableViewController: DiffableTimelineLikeTableViewController< completion(.failure(.client(error))) case let .success(newNotifications, _): + self.validateNotifications(newNotifications) guard !newNotifications.isEmpty else { completion(.failure(.allCaughtUp)) return diff --git a/Tusker/Views/Notifications/ActionNotificationGroupTableViewCell.swift b/Tusker/Views/Notifications/ActionNotificationGroupTableViewCell.swift index 03f4f022..08f2edac 100644 --- a/Tusker/Views/Notifications/ActionNotificationGroupTableViewCell.swift +++ b/Tusker/Views/Notifications/ActionNotificationGroupTableViewCell.swift @@ -9,6 +9,7 @@ import UIKit import Pachyderm import SwiftSoup +import Sentry class ActionNotificationGroupTableViewCell: UITableViewCell { @@ -66,7 +67,17 @@ class ActionNotificationGroupTableViewCell: UITableViewCell { self.group = group guard let firstNotification = group.notifications.first else { fatalError() } - let status = firstNotification.status! + guard let status = firstNotification.status else { + let crumb = Breadcrumb(level: .fatal, category: "notifications") + crumb.data = [ + "id": firstNotification.id, + "type": firstNotification.kind.rawValue, + "created_at": firstNotification.createdAt.formatted(.iso8601), + "account": firstNotification.account.id, + ] + SentrySDK.addBreadcrumb(crumb: crumb) + fatalError("missing status for favorite/reblog notification") + } self.statusID = status.id updateUIForPreferences()