Skip to content

Commit ae5783a

Browse files
committed
Improvement in cell reconfiguration
1 parent 42fed0c commit ae5783a

File tree

4 files changed

+26
-7
lines changed

4 files changed

+26
-7
lines changed

ChatLayout.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'ChatLayout'
3-
s.version = '2.0.7'
3+
s.version = '2.0.8'
44
s.summary = 'Chat UI Library. It uses custom UICollectionViewLayout to provide you full control over the presentation.'
55
s.swift_version = '5.8'
66

ChatLayout/Classes/Core/CollectionViewChatLayout.swift

+8-2
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,7 @@ open class CollectionViewChatLayout: UICollectionViewLayout {
615615
let shouldInvalidateLayout = cachedCollectionViewSize != .some(newBounds.size) ||
616616
cachedCollectionViewInset != .some(adjustedContentInset) ||
617617
invalidationActions.contains(.shouldInvalidateOnBoundsChange)
618+
|| (isUserInitiatedScrolling && state == .beforeUpdate)
618619

619620
invalidationActions.remove(.shouldInvalidateOnBoundsChange)
620621
return shouldInvalidateLayout
@@ -723,8 +724,13 @@ open class CollectionViewChatLayout: UICollectionViewLayout {
723724
let cell = collectionView.cellForItem(at: indexPath)
724725

725726
if let originalAttributes = controller.itemAttributes(for: indexPath.itemPath, kind: .cell, at: .beforeUpdate),
726-
let preferredAttributes = cell?.preferredLayoutAttributesFitting(originalAttributes),
727-
shouldInvalidateLayout(forPreferredLayoutAttributes: preferredAttributes, withOriginalAttributes: originalAttributes) {
727+
let preferredAttributes = cell?.preferredLayoutAttributesFitting(originalAttributes.typedCopy()) as? ChatLayoutAttributes,
728+
let itemIdentifierBeforeUpdate = controller.itemIdentifier(for: indexPath.itemPath, kind: .cell, at: .beforeUpdate),
729+
let indexPathAfterUpdate = controller.itemPath(by: itemIdentifierBeforeUpdate, kind: .cell, at: .afterUpdate)?.indexPath,
730+
let itemAfterUpdate = controller.item(for: indexPathAfterUpdate.itemPath, kind: .cell, at: .afterUpdate),
731+
(itemAfterUpdate.size.height - preferredAttributes.size.height).rounded() != 0 {
732+
originalAttributes.indexPath = indexPathAfterUpdate
733+
preferredAttributes.indexPath = indexPathAfterUpdate
728734
_ = invalidationContext(forPreferredLayoutAttributes: preferredAttributes, withOriginalAttributes: originalAttributes)
729735
}
730736
}

ChatLayout/Classes/Core/Model/LayoutModel.swift

-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ final class LayoutModel<Layout: ChatLayoutRepresentation> {
110110

111111
func itemPath(by itemId: UUID, kind: ItemKind) -> ItemPath? {
112112
guard let itemPathByIdentifierCache else {
113-
assertionFailure("Internal inconsistency. Cache is not prepared.")
114113
for (sectionIndex, section) in sections.enumerated() {
115114
switch kind {
116115
case .header:

ChatLayout/Classes/Core/Model/StateController.swift

+17-3
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@ final class StateController<Layout: ChatLayoutRepresentation> {
546546
var insertedSectionsIndexesArray = [(Int, SectionModel<Layout>?)]()
547547

548548
var reloadedItemsIndexesArray = [IndexPath]()
549+
var reconfiguredItemsIndexesArray = [IndexPath]()
549550
var deletedItemsIndexesArray = [IndexPath]()
550551
var insertedItemsIndexesArray = [(IndexPath, ItemModel?)]()
551552

@@ -562,9 +563,7 @@ final class StateController<Layout: ChatLayoutRepresentation> {
562563

563564
reloadedItemsIndexesArray.append(indexPath)
564565
case let .itemReconfigure(itemIndexPath: indexPath):
565-
reconfiguredIndexes.insert(indexPath)
566-
567-
reloadedItemsIndexesArray.append(indexPath)
566+
reconfiguredItemsIndexesArray.append(indexPath)
568567
case let .sectionDelete(sectionIndex):
569568
deletedSectionsIndexes.insert(sectionIndex)
570569

@@ -796,6 +795,21 @@ final class StateController<Layout: ChatLayoutRepresentation> {
796795
}
797796
}
798797

798+
for indexPath in reconfiguredItemsIndexesArray {
799+
guard var item = item(for: indexPath.itemPath, kind: .cell, at: .beforeUpdate),
800+
let indexPathAfterUpdate = afterUpdateModel.itemPath(by: item.id, kind: .cell)?.indexPath else {
801+
assertionFailure("Item at index path (\(indexPath.section) - \(indexPath.item)) does not exist.")
802+
continue
803+
}
804+
reconfiguredIndexes.insert(indexPathAfterUpdate)
805+
806+
let oldHeight = item.frame.height
807+
let configuration = layoutRepresentation.configuration(for: .cell, at: indexPathAfterUpdate)
808+
applyConfiguration(configuration, to: &item)
809+
afterUpdateModel.replaceItem(item, at: indexPathAfterUpdate)
810+
visibleBoundsBeforeUpdate.offsettingBy(dx: 0, dy: item.frame.height - oldHeight)
811+
}
812+
799813
var afterUpdateModelSections = afterUpdateModel.sections
800814
afterUpdateModelSections.withUnsafeMutableBufferPointer { directlyMutableSections in
801815
for index in 0..<directlyMutableSections.count {

0 commit comments

Comments
 (0)