IceCubesApp/Packages/Notifications/Sources/Notifications/NotificationsViewModel.swift

99 lines
3.3 KiB
Swift
Raw Normal View History

2022-12-19 11:28:55 +00:00
import Foundation
import SwiftUI
import Network
import Models
@MainActor
class NotificationsViewModel: ObservableObject {
public enum State {
public enum PagingState {
2022-12-29 09:39:34 +00:00
case none, hasNextPage, loadingNextPage
2022-12-19 11:28:55 +00:00
}
case loading
case display(notifications: [Models.Notification], nextPageState: State.PagingState)
case error(error: Error)
}
2022-12-22 06:00:44 +00:00
public enum Tab: String, CaseIterable {
case all = "All"
case mentions = "Mentions"
}
2022-12-30 07:36:22 +00:00
var client: Client? {
didSet {
if oldValue != client {
notifications = []
}
}
}
2022-12-19 11:28:55 +00:00
@Published var state: State = .loading
2022-12-22 06:00:44 +00:00
@Published var tab: Tab = .all {
didSet {
notifications = []
Task {
await fetchNotifications()
}
}
}
2022-12-19 11:28:55 +00:00
private var notifications: [Models.Notification] = []
private var queryTypes: [String]? {
tab == .mentions ? ["mention"] : nil
}
2022-12-19 11:28:55 +00:00
func fetchNotifications() async {
guard let client else { return }
do {
2022-12-29 09:39:34 +00:00
var nextPageState: State.PagingState = .hasNextPage
2022-12-21 16:39:48 +00:00
if notifications.isEmpty {
state = .loading
notifications = try await client.get(endpoint: Notifications.notifications(sinceId: nil,
maxId: nil,
types: queryTypes))
2022-12-29 09:39:34 +00:00
nextPageState = notifications.count < 15 ? .none : .hasNextPage
} else if let first = notifications.first {
let newNotifications: [Models.Notification] =
try await client.get(endpoint: Notifications.notifications(sinceId: first.id,
maxId: nil,
types: queryTypes))
2022-12-29 16:22:07 +00:00
nextPageState = notifications.count < 15 ? .none : .hasNextPage
notifications.insert(contentsOf: newNotifications, at: 0)
2022-12-21 16:39:48 +00:00
}
2022-12-29 09:39:34 +00:00
state = .display(notifications: notifications,
nextPageState: notifications.isEmpty ? .none : nextPageState)
2022-12-19 11:28:55 +00:00
} catch {
state = .error(error: error)
}
}
func fetchNextPage() async {
guard let client else { return }
do {
guard let lastId = notifications.last?.id else { return }
state = .display(notifications: notifications, nextPageState: .loadingNextPage)
let newNotifications: [Models.Notification] =
try await client.get(endpoint: Notifications.notifications(sinceId: nil,
maxId: lastId,
types: queryTypes))
2022-12-19 11:28:55 +00:00
notifications.append(contentsOf: newNotifications)
2022-12-29 09:39:34 +00:00
state = .display(notifications: notifications, nextPageState: newNotifications.count < 15 ? .none : .hasNextPage)
2022-12-19 11:28:55 +00:00
} catch {
state = .error(error: error)
}
}
2022-12-25 12:09:43 +00:00
func clear() async {
guard let client else { return }
do {
let _: ServerError = try await client.post(endpoint: Notifications.clear)
} catch { }
}
2022-12-25 12:09:43 +00:00
func handleEvent(event: any StreamEvent) {
if let event = event as? StreamEventNotification {
notifications.insert(event.notification, at: 0)
state = .display(notifications: notifications, nextPageState: .hasNextPage)
}
}
2022-12-19 11:28:55 +00:00
}