- P0: Add default param to protocol list(params:) for compile fix - P1: Fix onDelete async closure, implement deletion logic - P2: Remove redundant objectWillChange.send() (Published handles it) - P2: Make RelativeDateTimeFormatter static singleton (per-row perf) - P3: Replace deprecated NavigationView with NavigationStack
81 lines
2.4 KiB
Swift
81 lines
2.4 KiB
Swift
import Foundation
|
|
import SwiftUI
|
|
|
|
@MainActor
|
|
class NotificationsViewModel: ObservableObject {
|
|
@Published var notifications: [NotificationItem] = []
|
|
@Published var isLoading: Bool = false
|
|
@Published var badgeCount: Int = 0
|
|
@Published var lastRefreshDate: Date?
|
|
@Published var error: NotificationError?
|
|
|
|
private let notificationsService: NotificationsServiceProtocol
|
|
|
|
init(notificationsService: NotificationsServiceProtocol = NotificationsService()) {
|
|
self.notificationsService = notificationsService
|
|
}
|
|
|
|
func fetchNotifications() async {
|
|
isLoading = true
|
|
error = nil
|
|
defer {
|
|
isLoading = false
|
|
lastRefreshDate = Date()
|
|
}
|
|
|
|
do {
|
|
let fetchedNotifications = try await notificationsService.list()
|
|
notifications = fetchedNotifications.sorted { $0.createdAt > $1.createdAt }
|
|
badgeCount = notifications.filter { !$0.isRead }.count
|
|
} catch let error as NotificationError {
|
|
self.error = error
|
|
} catch {
|
|
print("Failed to fetch notifications: \(error)")
|
|
}
|
|
}
|
|
|
|
func refresh() async {
|
|
await fetchNotifications()
|
|
}
|
|
|
|
func fetchUnreadCount() async {
|
|
do {
|
|
let count = try await notificationsService.getUnreadCount()
|
|
badgeCount = count
|
|
} catch {
|
|
print("Failed to fetch unread count: \(error)")
|
|
}
|
|
}
|
|
|
|
func markAsRead(id: String) async {
|
|
guard let index = notifications.firstIndex(where: { $0.id == id }) else { return }
|
|
|
|
do {
|
|
try await notificationsService.markAsRead(id: id)
|
|
notifications[index].isRead = true
|
|
badgeCount = max(0, badgeCount - 1)
|
|
} catch {
|
|
print("Failed to mark notification as read: \(error)")
|
|
}
|
|
}
|
|
|
|
func markAllAsRead() async {
|
|
let unreadIds = notifications.filter { !$0.isRead }.map { $0.id }
|
|
guard !unreadIds.isEmpty else { return }
|
|
|
|
do {
|
|
try await notificationsService.markAllAsRead()
|
|
for index in notifications.indices {
|
|
notifications[index].isRead = true
|
|
}
|
|
badgeCount = 0
|
|
} catch {
|
|
print("Failed to mark all as read: \(error)")
|
|
}
|
|
}
|
|
|
|
var unreadCount: Int {
|
|
notifications.filter { !$0.isRead }.count
|
|
}
|
|
}
|