Slather logo

Coverage for "ChangeItem.swift" : 34.44%

(31 of 90 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 {
12x
95
        switch self {
12x
96
        case .sectionReload:
12x
97
            return 0
!
98
        case .itemReload:
12x
99
            return 1
4x
100
        case .sectionDelete:
12x
101
            return 2
!
102
        case .itemDelete:
12x
103
            return 3
3x
104
        case .sectionInsert:
12x
105
            return 4
!
106
        case .itemInsert:
12x
107
            return 5
3x
108
        case .sectionMove:
12x
109
            return 6
!
110
        case .itemMove:
12x
111
            return 7
2x
112
        }
12x
113
    }
12x
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
1x
123
        case let (.itemDelete(itemIndexPath: lIndexPath), .itemDelete(itemIndexPath: rIndexPath)):
124
            return lIndexPath < rIndexPath
99900x
125
        case let (.sectionInsert(sectionIndex: lIndex), .sectionInsert(sectionIndex: rIndex)):
126
            return lIndex < rIndex
1x
127
        case let (.itemInsert(itemIndexPath: lIndexPath), .itemInsert(itemIndexPath: rIndexPath)):
128
            return lIndexPath < rIndexPath
99900x
129
        case let (.sectionReload(sectionIndex: lIndex), .sectionReload(sectionIndex: rIndex)):
130
            return lIndex < rIndex
3x
131
        case let (.itemReload(itemIndexPath: lIndexPath), .itemReload(itemIndexPath: rIndexPath)):
132
            return lIndexPath < rIndexPath
10200x
133
        case let (.sectionMove(initialSectionIndex: lInitialSectionIndex, finalSectionIndex: lFinalSectionIndex),
134
                  .sectionMove(initialSectionIndex: rInitialSectionIndex, finalSectionIndex: rFinalSectionIndex)):
1x
135
            if lInitialSectionIndex == rInitialSectionIndex {
1x
136
                return lFinalSectionIndex < rFinalSectionIndex
!
137
            } else {
1x
138
                return lInitialSectionIndex < rInitialSectionIndex
1x
139
            }
140
        case let (.itemMove(initialItemIndexPath: lInitialIndexPath, finalItemIndexPath: lFinalIndexPath),
141
                  .itemMove(initialItemIndexPath: rInitialIndexPath, finalItemIndexPath: rFinalIndexPath)):
2x
142
            if lInitialIndexPath == rInitialIndexPath {
2x
143
                return lFinalIndexPath < rFinalIndexPath
!
144
            } else {
2x
145
                return lInitialIndexPath < rInitialIndexPath
2x
146
            }
147
        default:
148
            return lhs.rawValue < rhs.rawValue
6x
149
        }
150
    }
151
152
}