Mark notifications on Mastodon web frontend as read once displayed

Fixes #357
This commit is contained in:
Shadowfacts 2024-04-01 19:51:57 -04:00
parent 7affa09e5e
commit c73784aa81
2 changed files with 51 additions and 0 deletions

View File

@ -12,6 +12,9 @@ import Combine
#if canImport(Sentry) #if canImport(Sentry)
import Sentry import Sentry
#endif #endif
import OSLog
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "NotificationsCVC")
class NotificationsCollectionViewController: UIViewController, TimelineLikeCollectionViewController, CollectionViewController { class NotificationsCollectionViewController: UIViewController, TimelineLikeCollectionViewController, CollectionViewController {
@ -32,6 +35,9 @@ class NotificationsCollectionViewController: UIViewController, TimelineLikeColle
private var newer: RequestRange? private var newer: RequestRange?
private var older: RequestRange? private var older: RequestRange?
var updatesNotificationsMarker: Bool = false
private var newestDisplayedNotification: Item?
init(allowedTypes: [Pachyderm.Notification.Kind], mastodonController: MastodonController) { init(allowedTypes: [Pachyderm.Notification.Kind], mastodonController: MastodonController) {
self.allowedTypes = allowedTypes self.allowedTypes = allowedTypes
self.mastodonController = mastodonController self.mastodonController = mastodonController
@ -205,6 +211,12 @@ class NotificationsCollectionViewController: UIViewController, TimelineLikeColle
} }
} }
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
updateNotificationsMarkerIfNecessary()
}
@objc func refresh() { @objc func refresh() {
Task { @MainActor in Task { @MainActor in
if case .notLoadedInitial = controller.state { if case .notLoadedInitial = controller.state {
@ -311,6 +323,23 @@ class NotificationsCollectionViewController: UIViewController, TimelineLikeColle
await apply(snapshot, animatingDifferences: true) await apply(snapshot, animatingDifferences: true)
} }
private func updateNotificationsMarkerIfNecessary() {
guard updatesNotificationsMarker,
case let .group(group, _, _) = newestDisplayedNotification,
let notification = group.notifications.first else {
return
}
logger.debug("Updating notifications marker with \(notification.id)")
Task {
let req = TimelineMarkers.update(timeline: .notifications, lastReadID: notification.id)
do {
_ = try await mastodonController.run(req)
} catch {
logger.error("Failed to update notifications marker: \(String(describing: error))")
}
}
}
} }
extension NotificationsCollectionViewController { extension NotificationsCollectionViewController {
@ -545,6 +574,21 @@ extension NotificationsCollectionViewController: UICollectionViewDelegate {
guard case .notifications = dataSource.sectionIdentifier(for: indexPath.section) else { guard case .notifications = dataSource.sectionIdentifier(for: indexPath.section) else {
return return
} }
if updatesNotificationsMarker {
let shouldUpdateNewestDisplayedNotification: Bool
if let newestDisplayedNotification,
let currentNewestIndexPath = dataSource.indexPath(for: newestDisplayedNotification) {
shouldUpdateNewestDisplayedNotification = indexPath < currentNewestIndexPath
} else {
shouldUpdateNewestDisplayedNotification = true
}
if shouldUpdateNewestDisplayedNotification,
let item = dataSource.itemIdentifier(for: indexPath) {
newestDisplayedNotification = item
}
}
let itemsInSection = collectionView.numberOfItems(inSection: indexPath.section) let itemsInSection = collectionView.numberOfItems(inSection: indexPath.section)
if indexPath.row == itemsInSection - 1 { if indexPath.row == itemsInSection - 1 {
Task { Task {
@ -765,3 +809,9 @@ extension NotificationsCollectionViewController: StatusBarTappableViewController
return .stop return .stop
} }
} }
extension NotificationsCollectionViewController: BackgroundableViewController {
func sceneDidEnterBackground() {
updateNotificationsMarkerIfNecessary()
}
}

View File

@ -24,6 +24,7 @@ class NotificationsPageViewController: SegmentedPageViewController<Notifications
let vc = NotificationsCollectionViewController(allowedTypes: page.allowedTypes, mastodonController: mastodonController) let vc = NotificationsCollectionViewController(allowedTypes: page.allowedTypes, mastodonController: mastodonController)
vc.title = page.title vc.title = page.title
vc.userActivity = page.userActivity(accountID: mastodonController.accountInfo!.id) vc.userActivity = page.userActivity(accountID: mastodonController.accountInfo!.id)
vc.updatesNotificationsMarker = page == .all
return vc return vc
} }