2
2
mirror of https://github.com/mastodon/mastodon-ios synced 2025-04-11 22:58:02 +02:00

Regularly update the time-elapsed stamps in the notification views

Contributes to #399 [BUG] Multiple interactions do not collapse into a single notification
This commit is contained in:
shannon 2025-03-11 11:02:05 -04:00
parent 77f81e5849
commit 6783182e21
4 changed files with 34 additions and 7 deletions

View File

@ -51,6 +51,8 @@ final public class GroupedNotificationFeedLoader {
return cacheManager?.currentLastReadMarker
}
private let timestampUpdater = TimestampUpdater(TimeInterval(30))
private var isFetching: Bool = false
public let useGroupedNotificationsApi: Bool
@ -319,7 +321,7 @@ extension GroupedNotificationFeedLoader {
if let ungrouped = results as? [Mastodon.Entity.Notification] {
return NotificationRowViewModel.viewModelsFromUngroupedNotifications(
ungrouped, myAccountID: authenticationBox.userID,
ungrouped, timestamper: timestampUpdater, myAccountID: authenticationBox.userID,
myAccountDomain: authenticationBox.domain,
navigateToScene: navigateToScene ?? { _, _ in },
presentError: presentError ?? { _ in }
@ -328,6 +330,7 @@ extension GroupedNotificationFeedLoader {
return NotificationRowViewModel
.viewModelsFromGroupedNotificationResults(
grouped,
timestamper: timestampUpdater,
myAccountID: authenticationBox.userID,
myAccountDomain: authenticationBox.domain,
navigateToScene: navigateToScene ?? { _, _ in },
@ -363,3 +366,16 @@ extension NotificationRowViewModel: Hashable {
hasher.combine(identifier)
}
}
class TimestampUpdater: ObservableObject {
@Published var timestamp: Date = .now
private var timer: Timer?
init(_ interval: TimeInterval) {
timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true, block: { [weak self] _ in
Task { @MainActor in
self?.timestamp = .now
}
})
}
}

View File

@ -532,6 +532,12 @@ let actionSuperheaderHeight: CGFloat = 20
struct NotificationRowView: View {
@ObservedObject var viewModel: NotificationRowViewModel
@ObservedObject var timestamper: TimestampUpdater
init(viewModel: NotificationRowViewModel) {
self.viewModel = viewModel
self.timestamper = viewModel.timestampUpdater
}
var body: some View {
HStack(alignment: .top, spacing: avatarSpacing) {
@ -602,7 +608,7 @@ struct NotificationRowView: View {
Text(string)
.frame(maxWidth: .infinity, alignment: .leading)
case .timeSinceLabel(let date):
Text(date.localizedExtremelyAbbreviatedTimeElapsedUntilNow)
Text(date.localizedExtremelyAbbreviatedTimeElapsedUntil(now: timestamper.timestamp))
.font(.subheadline)
.frame(height: actionSuperheaderHeight)
.fixedSize(horizontal: true, vertical: false)
@ -628,7 +634,7 @@ struct NotificationRowView: View {
HStack(alignment: .top, spacing: 2) {
Text(string)
.frame(maxWidth: .infinity, alignment: .leading)
Text(date.localizedExtremelyAbbreviatedTimeElapsedUntilNow)
Text(date.localizedExtremelyAbbreviatedTimeElapsedUntil(now: timestamper.timestamp))
.font(.subheadline)
.frame(height: actionSuperheaderHeight)
.fixedSize(horizontal: true, vertical: false)

View File

@ -11,6 +11,7 @@ import SwiftUICore
class NotificationRowViewModel: ObservableObject {
let identifier: MastodonFeedItemIdentifier
let timestamp: Date?
let timestampUpdater: TimestampUpdater
let oldestID: String?
let newestID: String?
let type: GroupedNotificationType
@ -45,6 +46,7 @@ class NotificationRowViewModel: ObservableObject {
init(
_ notificationInfo: GroupedNotificationInfo,
timestamper: TimestampUpdater,
myAccountDomain: String,
navigateToScene: @escaping (
SceneCoordinator.Scene, SceneCoordinator.Transition
@ -53,6 +55,7 @@ class NotificationRowViewModel: ObservableObject {
self.identifier = .notificationGroup(id: notificationInfo.id)
self.timestamp = notificationInfo.timestamp
self.timestampUpdater = timestamper
self.oldestID = notificationInfo.oldestNotificationID
self.newestID = notificationInfo.newestNotificationID
self.type = notificationInfo.groupedNotificationType
@ -526,6 +529,7 @@ extension NotificationRowViewModel {
extension NotificationRowViewModel {
static func viewModelsFromGroupedNotificationResults(
_ results: Mastodon.Entity.GroupedNotificationsResults,
timestamper: TimestampUpdater,
myAccountID: String,
myAccountDomain: String,
navigateToScene: @escaping (
@ -607,7 +611,7 @@ extension NotificationRowViewModel {
)
return NotificationRowViewModel(
info, myAccountDomain: myAccountDomain,
info, timestamper: timestamper, myAccountDomain: myAccountDomain,
navigateToScene: navigateToScene,
presentError: presentError)
}
@ -615,6 +619,7 @@ extension NotificationRowViewModel {
static func viewModelsFromUngroupedNotifications(
_ notifications: [Mastodon.Entity.Notification],
timestamper: TimestampUpdater,
myAccountID: String,
myAccountDomain: String,
navigateToScene: @escaping (
@ -675,7 +680,7 @@ extension NotificationRowViewModel {
)
return NotificationRowViewModel(
info, myAccountDomain: myAccountDomain,
info, timestamper: timestamper, myAccountDomain: myAccountDomain,
navigateToScene: navigateToScene,
presentError: presentError)
}

View File

@ -44,8 +44,8 @@ extension Date {
return Date.relativeTimestampFormatter.localizedString(for: self, relativeTo: Date())
}
public var localizedExtremelyAbbreviatedTimeElapsedUntilNow: String {
let interval = Date.now.timeIntervalSince(self)
public func localizedExtremelyAbbreviatedTimeElapsedUntil(now: Date) -> String {
let interval = now.timeIntervalSince(self)
guard interval > TimeInterval(integerLiteral: 60) else { return "now" }
return extremeDateAbbreviatingFormatter.string(from: interval) ?? ""
}