118 lines
4.3 KiB
Swift
118 lines
4.3 KiB
Swift
//
|
|
// NotificationGroup.swift
|
|
// Pachyderm
|
|
//
|
|
// Created by Shadowfacts on 9/5/19.
|
|
// Copyright © 2019 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
public struct NotificationGroup: Identifiable, Hashable {
|
|
public private(set) var notifications: [Notification]
|
|
public let id: String
|
|
public let kind: Notification.Kind
|
|
public let statusState: CollapseState?
|
|
|
|
init?(notifications: [Notification]) {
|
|
guard !notifications.isEmpty else { return nil }
|
|
self.notifications = notifications
|
|
self.id = notifications.first!.id
|
|
self.kind = notifications.first!.kind
|
|
if kind == .mention {
|
|
self.statusState = .unknown
|
|
} else {
|
|
self.statusState = nil
|
|
}
|
|
}
|
|
|
|
public static func ==(lhs: NotificationGroup, rhs: NotificationGroup) -> Bool {
|
|
guard lhs.notifications.count == rhs.notifications.count else {
|
|
return false
|
|
}
|
|
for (a, b) in zip(lhs.notifications, rhs.notifications) where a.id != b.id {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
public func hash(into hasher: inout Hasher) {
|
|
for notification in notifications {
|
|
hasher.combine(notification.id)
|
|
}
|
|
}
|
|
|
|
private mutating func append(_ notification: Notification) {
|
|
notifications.append(notification)
|
|
}
|
|
|
|
private mutating func append(group: NotificationGroup) {
|
|
notifications.append(contentsOf: group.notifications)
|
|
}
|
|
|
|
public static func createGroups(notifications: [Notification], only allowedTypes: [Notification.Kind]) -> [NotificationGroup] {
|
|
var groups = [NotificationGroup]()
|
|
for notification in notifications {
|
|
if allowedTypes.contains(notification.kind) {
|
|
if let lastGroup = groups.last, canMerge(notification: notification, into: lastGroup) {
|
|
groups[groups.count - 1].append(notification)
|
|
continue
|
|
} else if groups.count >= 2 {
|
|
let secondToLastGroup = groups[groups.count - 2]
|
|
if allowedTypes.contains(groups[groups.count - 1].kind), canMerge(notification: notification, into: secondToLastGroup) {
|
|
groups[groups.count - 2].append(notification)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
groups.append(NotificationGroup(notifications: [notification])!)
|
|
}
|
|
return groups
|
|
}
|
|
|
|
private static func canMerge(notification: Notification, into group: NotificationGroup) -> Bool {
|
|
return notification.kind == group.kind && notification.status?.id == group.notifications.first!.status?.id
|
|
}
|
|
|
|
public static func mergeGroups(first: [NotificationGroup], second: [NotificationGroup], only allowedTypes: [Notification.Kind]) -> [NotificationGroup] {
|
|
guard !first.isEmpty else {
|
|
return second
|
|
}
|
|
guard !second.isEmpty else {
|
|
return first
|
|
}
|
|
|
|
var merged = first
|
|
var second = second
|
|
merged.reserveCapacity(second.count)
|
|
while let firstGroupFromSecond = second.first,
|
|
allowedTypes.contains(firstGroupFromSecond.kind) {
|
|
|
|
second.removeFirst()
|
|
|
|
guard let lastGroup = merged.last,
|
|
allowedTypes.contains(lastGroup.kind) else {
|
|
merged.append(firstGroupFromSecond)
|
|
break
|
|
}
|
|
|
|
if canMerge(notification: firstGroupFromSecond.notifications.first!, into: lastGroup) {
|
|
merged[merged.count - 1].append(group: firstGroupFromSecond)
|
|
} else if merged.count >= 2 {
|
|
let secondToLastGroup = merged[merged.count - 2]
|
|
if allowedTypes.contains(secondToLastGroup.kind), canMerge(notification: firstGroupFromSecond.notifications.first!, into: secondToLastGroup) {
|
|
merged[merged.count - 2].append(group: firstGroupFromSecond)
|
|
} else {
|
|
merged.append(firstGroupFromSecond)
|
|
}
|
|
} else {
|
|
merged.append(firstGroupFromSecond)
|
|
}
|
|
}
|
|
merged.append(contentsOf: second)
|
|
return merged
|
|
}
|
|
|
|
}
|