109 lines
3.0 KiB
Swift
109 lines
3.0 KiB
Swift
import Foundation
|
|
|
|
@Observable
|
|
final class BugStore {
|
|
static let shared = BugStore()
|
|
|
|
private(set) var bugs: [Bug] = []
|
|
private(set) var unseenBugs: Set<String> = []
|
|
private(set) var lastUpdated: Date?
|
|
private(set) var isLoading = false
|
|
private(set) var error: Error?
|
|
|
|
var activeBugs: [Bug] {
|
|
bugs.filter { $0.status != .closed && $0.status != .resolved }
|
|
}
|
|
|
|
var unseenActiveCount: Int {
|
|
activeBugs.filter { unseenBugs.contains($0.id) }.count
|
|
}
|
|
|
|
var bugsSortedByPriority: [Bug] {
|
|
activeBugs.sorted { lhs, rhs in
|
|
if lhs.priority != rhs.priority {
|
|
return lhs.priority < rhs.priority
|
|
}
|
|
return lhs.createdAt < rhs.createdAt
|
|
}
|
|
}
|
|
|
|
private init() {
|
|
unseenBugs = AppStateService.shared.persistedSeenBugs
|
|
}
|
|
|
|
func update(with newBugs: [Bug]) {
|
|
let oldBugs = bugs
|
|
let oldIDs = Set(oldBugs.map(\.id))
|
|
let newIDs = Set(newBugs.map(\.id))
|
|
let added = newIDs.subtracting(oldIDs)
|
|
|
|
unseenBugs.formUnion(added)
|
|
|
|
let changes = detectChanges(old: oldBugs, new: newBugs)
|
|
if !changes.isEmpty {
|
|
Task {
|
|
await NotificationService.shared.handleChanges(changes)
|
|
}
|
|
}
|
|
|
|
bugs = newBugs
|
|
lastUpdated = Date()
|
|
error = nil
|
|
AppStateService.shared.updateSeenBugs(unseenBugs)
|
|
}
|
|
|
|
func markSeen(_ bugID: String) {
|
|
unseenBugs.remove(bugID)
|
|
AppStateService.shared.updateSeenBugs(unseenBugs)
|
|
}
|
|
|
|
func markAllSeen() {
|
|
unseenBugs.removeAll()
|
|
AppStateService.shared.updateSeenBugs(unseenBugs)
|
|
}
|
|
|
|
func setLoading(_ loading: Bool) {
|
|
isLoading = loading
|
|
}
|
|
|
|
func setError(_ error: Error?) {
|
|
self.error = error
|
|
}
|
|
|
|
private func detectChanges(old: [Bug], new: [Bug]) -> [BugChange] {
|
|
let oldMap = Dictionary(uniqueKeysWithValues: old.map { ($0.id, $0) })
|
|
var changes: [BugChange] = []
|
|
|
|
for newBug in new {
|
|
guard let oldBug = oldMap[newBug.id] else {
|
|
changes.append(
|
|
BugChange(type: .newBug, bug: newBug, oldStatus: nil, oldAssignee: nil)
|
|
)
|
|
continue
|
|
}
|
|
if oldBug.status != newBug.status {
|
|
changes.append(
|
|
BugChange(type: .statusChanged, bug: newBug, oldStatus: oldBug.status, oldAssignee: nil)
|
|
)
|
|
}
|
|
if oldBug.priority != newBug.priority {
|
|
changes.append(
|
|
BugChange(type: .priorityChanged, bug: newBug, oldStatus: nil, oldAssignee: nil)
|
|
)
|
|
}
|
|
if oldBug.assignee != newBug.assignee {
|
|
changes.append(
|
|
BugChange(
|
|
type: .assigneeChanged,
|
|
bug: newBug,
|
|
oldStatus: nil,
|
|
oldAssignee: oldBug.assignee
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
return changes
|
|
}
|
|
}
|