Skip to content

Commit

Permalink
Improvement in cell reconfiguration
Browse files Browse the repository at this point in the history
  • Loading branch information
ekazaev committed May 15, 2024
1 parent 42fed0c commit ae5783a
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 7 deletions.
2 changes: 1 addition & 1 deletion ChatLayout.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'ChatLayout'
s.version = '2.0.7'
s.version = '2.0.8'
s.summary = 'Chat UI Library. It uses custom UICollectionViewLayout to provide you full control over the presentation.'
s.swift_version = '5.8'

Expand Down
10 changes: 8 additions & 2 deletions ChatLayout/Classes/Core/CollectionViewChatLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ open class CollectionViewChatLayout: UICollectionViewLayout {
let shouldInvalidateLayout = cachedCollectionViewSize != .some(newBounds.size) ||
cachedCollectionViewInset != .some(adjustedContentInset) ||
invalidationActions.contains(.shouldInvalidateOnBoundsChange)
|| (isUserInitiatedScrolling && state == .beforeUpdate)

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

if let originalAttributes = controller.itemAttributes(for: indexPath.itemPath, kind: .cell, at: .beforeUpdate),
let preferredAttributes = cell?.preferredLayoutAttributesFitting(originalAttributes),
shouldInvalidateLayout(forPreferredLayoutAttributes: preferredAttributes, withOriginalAttributes: originalAttributes) {
let preferredAttributes = cell?.preferredLayoutAttributesFitting(originalAttributes.typedCopy()) as? ChatLayoutAttributes,
let itemIdentifierBeforeUpdate = controller.itemIdentifier(for: indexPath.itemPath, kind: .cell, at: .beforeUpdate),
let indexPathAfterUpdate = controller.itemPath(by: itemIdentifierBeforeUpdate, kind: .cell, at: .afterUpdate)?.indexPath,
let itemAfterUpdate = controller.item(for: indexPathAfterUpdate.itemPath, kind: .cell, at: .afterUpdate),
(itemAfterUpdate.size.height - preferredAttributes.size.height).rounded() != 0 {
originalAttributes.indexPath = indexPathAfterUpdate
preferredAttributes.indexPath = indexPathAfterUpdate
_ = invalidationContext(forPreferredLayoutAttributes: preferredAttributes, withOriginalAttributes: originalAttributes)
}
}
Expand Down
1 change: 0 additions & 1 deletion ChatLayout/Classes/Core/Model/LayoutModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ final class LayoutModel<Layout: ChatLayoutRepresentation> {

func itemPath(by itemId: UUID, kind: ItemKind) -> ItemPath? {
guard let itemPathByIdentifierCache else {
assertionFailure("Internal inconsistency. Cache is not prepared.")
for (sectionIndex, section) in sections.enumerated() {
switch kind {
case .header:
Expand Down
20 changes: 17 additions & 3 deletions ChatLayout/Classes/Core/Model/StateController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ final class StateController<Layout: ChatLayoutRepresentation> {
var insertedSectionsIndexesArray = [(Int, SectionModel<Layout>?)]()

var reloadedItemsIndexesArray = [IndexPath]()
var reconfiguredItemsIndexesArray = [IndexPath]()
var deletedItemsIndexesArray = [IndexPath]()
var insertedItemsIndexesArray = [(IndexPath, ItemModel?)]()

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

reloadedItemsIndexesArray.append(indexPath)
case let .itemReconfigure(itemIndexPath: indexPath):
reconfiguredIndexes.insert(indexPath)

reloadedItemsIndexesArray.append(indexPath)
reconfiguredItemsIndexesArray.append(indexPath)
case let .sectionDelete(sectionIndex):
deletedSectionsIndexes.insert(sectionIndex)

Expand Down Expand Up @@ -796,6 +795,21 @@ final class StateController<Layout: ChatLayoutRepresentation> {
}
}

for indexPath in reconfiguredItemsIndexesArray {
guard var item = item(for: indexPath.itemPath, kind: .cell, at: .beforeUpdate),
let indexPathAfterUpdate = afterUpdateModel.itemPath(by: item.id, kind: .cell)?.indexPath else {
assertionFailure("Item at index path (\(indexPath.section) - \(indexPath.item)) does not exist.")
continue
}
reconfiguredIndexes.insert(indexPathAfterUpdate)

let oldHeight = item.frame.height
let configuration = layoutRepresentation.configuration(for: .cell, at: indexPathAfterUpdate)
applyConfiguration(configuration, to: &item)
afterUpdateModel.replaceItem(item, at: indexPathAfterUpdate)
visibleBoundsBeforeUpdate.offsettingBy(dx: 0, dy: item.frame.height - oldHeight)
}

var afterUpdateModelSections = afterUpdateModel.sections
afterUpdateModelSections.withUnsafeMutableBufferPointer { directlyMutableSections in
for index in 0..<directlyMutableSections.count {
Expand Down

0 comments on commit ae5783a

Please sign in to comment.