Slather logo

Coverage for "ChangeItem.swift" : 0.00%

(0 of 105 relevant lines covered)

ChatLayout/Classes/Core/Model/ChangeItem.swift

1
//
2
// ChatLayout
3
// ChangeItem.swift
4
// https://github.com/ekazaev/ChatLayout
5
//
6
// Created by Eugene Kazaev in 2020-2022.
7
// Distributed under the MIT license.
8
//
9
10
import Foundation
11
import UIKit
12
13
/// Internal replacement for `UICollectionViewUpdateItem`.
14
enum ChangeItem: Equatable {
15
16
    /// Delete section at `sectionIndex`
17
    case sectionDelete(sectionIndex: Int)
18
19
    /// Delete item at `itemIndexPath`
20
    case itemDelete(itemIndexPath: IndexPath)
21
22
    /// Insert section at `sectionIndex`
23
    case sectionInsert(sectionIndex: Int)
24
25
    /// Insert item at `itemIndexPath`
26
    case itemInsert(itemIndexPath: IndexPath)
27
28
    /// Reload section at `sectionIndex`
29
    case sectionReload(sectionIndex: Int)
30
31
    /// Reload item at `itemIndexPath`
32
    case itemReload(itemIndexPath: IndexPath)
33
34
    /// Move section from `initialSectionIndex` to `finalSectionIndex`
35
    case sectionMove(initialSectionIndex: Int, finalSectionIndex: Int)
36
37
    /// Move item from `initialItemIndexPath` to `finalItemIndexPath`
38
    case itemMove(initialItemIndexPath: IndexPath, finalItemIndexPath: IndexPath)
39
40
    init?(with updateItem: UICollectionViewUpdateItem) {
!
41
        let updateAction = updateItem.updateAction
!
42
        let indexPathBeforeUpdate = updateItem.indexPathBeforeUpdate
!
43
        let indexPathAfterUpdate = updateItem.indexPathAfterUpdate
!
44
        switch updateAction {
!
45
        case .none:
!
46
            return nil
!
47
        case .move:
!
48
            guard let indexPathBeforeUpdate = indexPathBeforeUpdate,
!
49
                  let indexPathAfterUpdate = indexPathAfterUpdate else {
!
50
                assertionFailure("`indexPathBeforeUpdate` and `indexPathAfterUpdate` cannot be `nil` for a `.move` update action")
!
51
                return nil
!
52
            }
!
53
            if indexPathBeforeUpdate.item == NSNotFound, indexPathAfterUpdate.item == NSNotFound {
!
54
                self = .sectionMove(initialSectionIndex: indexPathBeforeUpdate.section, finalSectionIndex: indexPathAfterUpdate.section)
!
55
            } else {
!
56
                self = .itemMove(initialItemIndexPath: indexPathBeforeUpdate, finalItemIndexPath: indexPathAfterUpdate)
!
57
            }
!
58
        case .insert:
!
59
            guard let indexPath = indexPathAfterUpdate else {
!
60
                assertionFailure("`indexPathAfterUpdate` cannot be `nil` for an `.insert` update action")
!
61
                return nil
!
62
            }
!
63
            if indexPath.item == NSNotFound {
!
64
                self = .sectionInsert(sectionIndex: indexPath.section)
!
65
            } else {
!
66
                self = .itemInsert(itemIndexPath: indexPath)
!
67
            }
!
68
        case .delete:
!
69
            guard let indexPath = indexPathBeforeUpdate else {
!
70
                assertionFailure("`indexPathBeforeUpdate` cannot be `nil` for a `.delete` update action")
!
71
                return nil
!
72
            }
!
73
            if indexPath.item == NSNotFound {
!
74
                self = .sectionDelete(sectionIndex: indexPath.section)
!
75
            } else {
!
76
                self = .itemDelete(itemIndexPath: indexPath)
!
77
            }
!
78
        case .reload:
!
79
            guard let indexPath = indexPathAfterUpdate else {
!
80
                assertionFailure("`indexPathAfterUpdate` cannot be `nil` for a `.reload` update action")
!
81
                return nil
!
82
            }
!
83
!
84
            if indexPath.item == NSNotFound {
!
85
                self = .sectionReload(sectionIndex: indexPath.section)
!
86
            } else {
!
87
                self = .itemReload(itemIndexPath: indexPath)
!
88
            }
!
89
        @unknown default:
!
90
            return nil
!
91
        }
!
92
    }
!
93
94
    private var rawValue: Int {
!
95
        switch self {
!
96
        case .sectionReload:
!
97
            return 0
!
98
        case .itemReload:
!
99
            return 1
!
100
        case .sectionDelete:
!
101
            return 2
!
102
        case .itemDelete:
!
103
            return 3
!
104
        case .sectionInsert:
!
105
            return 4
!
106
        case .itemInsert:
!
107
            return 5
!
108
        case .sectionMove:
!
109
            return 6
!
110
        case .itemMove:
!
111
            return 7
!
112
        }
!
113
    }
!
114
115
}
116
117
extension ChangeItem: Comparable {
118
119
    static func < (lhs: ChangeItem, rhs: ChangeItem) -> Bool {
!
120
        switch (lhs, rhs) {
!
121
        case let (.sectionDelete(sectionIndex: lIndex), .sectionDelete(sectionIndex: rIndex)):
!
122
            return lIndex < rIndex
!
123
        case let (.itemDelete(itemIndexPath: lIndexPath), .itemDelete(itemIndexPath: rIndexPath)):
!
124
            return lIndexPath < rIndexPath
!
125
        case let (.sectionInsert(sectionIndex: lIndex), .sectionInsert(sectionIndex: rIndex)):
!
126
            return lIndex < rIndex
!
127
        case let (.itemInsert(itemIndexPath: lIndexPath), .itemInsert(itemIndexPath: rIndexPath)):
!
128
            return lIndexPath < rIndexPath
!
129
        case let (.sectionReload(sectionIndex: lIndex), .sectionReload(sectionIndex: rIndex)):
!
130
            return lIndex < rIndex
!
131
        case let (.itemReload(itemIndexPath: lIndexPath), .itemReload(itemIndexPath: rIndexPath)):
!
132
            return lIndexPath < rIndexPath
!
133
        case let (.sectionMove(initialSectionIndex: lInitialSectionIndex, finalSectionIndex: lFinalSectionIndex),
!
134
                  .sectionMove(initialSectionIndex: rInitialSectionIndex, finalSectionIndex: rFinalSectionIndex)):
!
135
            if lInitialSectionIndex == rInitialSectionIndex {
!
136
                return lFinalSectionIndex < rFinalSectionIndex
!
137
            } else {
!
138
                return lInitialSectionIndex < rInitialSectionIndex
!
139
            }
!
140
        case let (.itemMove(initialItemIndexPath: lInitialIndexPath, finalItemIndexPath: lFinalIndexPath),
!
141
                  .itemMove(initialItemIndexPath: rInitialIndexPath, finalItemIndexPath: rFinalIndexPath)):
!
142
            if lInitialIndexPath == rInitialIndexPath {
!
143
                return lFinalIndexPath < rFinalIndexPath
!
144
            } else {
!
145
                return lInitialIndexPath < rInitialIndexPath
!
146
            }
!
147
        default:
!
148
            return lhs.rawValue < rhs.rawValue
!
149
        }
!
150
    }
!
151
152
}