Skip to content

Commit

Permalink
Added processOnlyVisibleItemsOnAnimatedBatchUpdates for a finer con…
Browse files Browse the repository at this point in the history
…trol over animation process.
  • Loading branch information
ekazaev committed Nov 4, 2022
1 parent 1e9776c commit 3743433
Show file tree
Hide file tree
Showing 78 changed files with 2,247 additions and 2,082 deletions.
1 change: 0 additions & 1 deletion .jazzy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ custom_categories:
- ChatLayoutInvalidationContext
- ItemKind
- ItemSize
- ItemSize.CaseType
- ChatItemAlignment
- InitialAttributesRequestType

Expand Down
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 = '1.2.13'
s.version = '1.2.14'
s.summary = 'Chat UI Library. It uses custom UICollectionViewLayout to provide you full control over the presentation.'
s.swift_version = '5.7'

Expand Down
11 changes: 11 additions & 0 deletions ChatLayout/Classes/Core/CollectionViewChatLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import UIKit
///
/// `CollectionViewChatLayout.keepContentOffsetAtBottomOnBatchUpdates`
///
/// `CollectionViewChatLayout.processOnlyVisibleItemsOnAnimatedBatchUpdates`
///
/// `CollectionViewChatLayout.visibleBounds`
///
/// `CollectionViewChatLayout.layoutFrame`
Expand Down Expand Up @@ -58,6 +60,15 @@ public final class CollectionViewChatLayout: UICollectionViewLayout {
/// the animation starts and wont be able to compensate that change too. It should be done manually.
public var keepContentOffsetAtBottomOnBatchUpdates: Bool = false

/// Sometimes `UIScrollView` can behave weirdly if there are too many corrections in it's `contentOffset` during the animation. Especially when content size of the `UIScrollView`
// is getting smaller first and then expands again as the newly appearing cells sizes are being calculated. That is why `CollectionViewChatLayout`
/// tries to process only the elements that are currently visible on the screen. But often it is not needed. This flag allows you to have fine control over this behaviour.
/// It set to `true` by default to keep the compatibility with the older versions of the library.
///
/// **NB:**
/// This flag is only to provide fine control over the batch updates. If in doubts - keep it `true`.
public var processOnlyVisibleItemsOnAnimatedBatchUpdates: Bool = true

/// Represent the currently visible rectangle.
public var visibleBounds: CGRect {
guard let collectionView = collectionView else {
Expand Down
4 changes: 3 additions & 1 deletion ChatLayout/Classes/Core/Model/StateController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ protocol ChatLayoutRepresentation: AnyObject {

var keepContentOffsetAtBottomOnBatchUpdates: Bool { get }

var processOnlyVisibleItemsOnAnimatedBatchUpdates: Bool { get }

func numberOfItems(in section: Int) -> Int

func configuration(for element: ItemKind, at indexPath: IndexPath) -> ItemModel.Configuration
Expand Down Expand Up @@ -764,7 +766,7 @@ final class StateController<Layout: ChatLayoutRepresentation> {
let itemPath = ItemPath(item: itemIndex, section: sectionIndex)
if let itemFrame = itemFrame(for: itemPath, kind: .cell, at: state, isFinal: true, additionalAttributes: additionalAttributes),
check(rect: itemFrame) {
if state == .beforeUpdate || isAnimatedBoundsChange {
if state == .beforeUpdate || isAnimatedBoundsChange || !layoutRepresentation.processOnlyVisibleItemsOnAnimatedBatchUpdates {
allRects.append((frame: itemFrame, indexPath: itemPath, kind: .cell))
} else {
var itemWasVisibleBefore: Bool {
Expand Down
3 changes: 2 additions & 1 deletion ChatLayout/Classes/Extras/EdgeAligningView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ public final class EdgeAligningView<CustomView: UIView>: UIView {
let layoutConstraint = view.centerXAnchor.constraint(equalTo: layoutMarginsGuide.centerXAnchor)
addedConstraints.append(layoutConstraint)
layoutConstraint.isActive = true
} else if flexibleEdges.contains(.top), flexibleEdges.contains(.bottom) {
}
if flexibleEdges.contains(.top), flexibleEdges.contains(.bottom) {
let layoutConstraint = view.centerYAnchor.constraint(equalTo: layoutMarginsGuide.centerYAnchor)
addedConstraints.append(layoutConstraint)
layoutConstraint.isActive = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ import Foundation

protocol ChatControllerDelegate: AnyObject {

func update(with sections: [Section])
func update(with sections: [Section], requiresIsolatedProcess: Bool)

}
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,9 @@ final class DefaultChatController: ChatController {
}
}

private func repopulateMessages() {
private func repopulateMessages(requiresIsolatedProcess: Bool = false) {
propagateLatestMessages { sections in
self.delegate?.update(with: sections)
self.delegate?.update(with: sections, requiresIsolatedProcess: requiresIsolatedProcess)
}
}

Expand Down Expand Up @@ -305,7 +305,7 @@ extension DefaultChatController: EditingAccessoryControllerDelegate {

func deleteMessage(with id: UUID) {
messages = Array(messages.filter { $0.id != id })
repopulateMessages()
repopulateMessages(requiresIsolatedProcess: true)
}

}
24 changes: 17 additions & 7 deletions Example/ChatLayout/Chat/View/ChatViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ final class ChatViewController: UIViewController {
case scrollingToBottom
case showingPreview
case showingAccessory
case updatingCollectionInIsolation
}

private enum ControllerActions {
Expand Down Expand Up @@ -124,6 +125,7 @@ final class ChatViewController: UIViewController {
chatLayout.settings.interSectionSpacing = 8
chatLayout.settings.additionalInsets = UIEdgeInsets(top: 8, left: 5, bottom: 8, right: 5)
chatLayout.keepContentOffsetAtBottomOnBatchUpdates = true
chatLayout.processOnlyVisibleItemsOnAnimatedBatchUpdates = false

collectionView = UICollectionView(frame: view.frame, collectionViewLayout: chatLayout)
view.addSubview(collectionView)
Expand Down Expand Up @@ -156,7 +158,7 @@ final class ChatViewController: UIViewController {
currentControllerActions.options.insert(.loadingInitialMessages)
chatController.loadInitialMessages { sections in
self.currentControllerActions.options.remove(.loadingInitialMessages)
self.processUpdates(with: sections, animated: true)
self.processUpdates(with: sections, animated: true, requiresIsolatedProcess: false)
}

KeyboardListener.shared.add(delegate: self)
Expand Down Expand Up @@ -298,7 +300,7 @@ extension ChatViewController: UIScrollViewDelegate {
}
// Reloading the content without animation just because it looks better is the scrolling is in process.
let animated = !self.isUserInitiatedScrolling
self.processUpdates(with: sections, animated: animated) {
self.processUpdates(with: sections, animated: animated, requiresIsolatedProcess: false) {
self.currentControllerActions.options.remove(.loadingPreviousMessages)
}
}
Expand Down Expand Up @@ -441,11 +443,11 @@ extension ChatViewController: UICollectionViewDelegate {

extension ChatViewController: ChatControllerDelegate {

func update(with sections: [Section]) {
processUpdates(with: sections, animated: true)
func update(with sections: [Section], requiresIsolatedProcess: Bool) {
processUpdates(with: sections, animated: true, requiresIsolatedProcess: requiresIsolatedProcess)
}

private func processUpdates(with sections: [Section], animated: Bool = true, completion: (() -> Void)? = nil) {
private func processUpdates(with sections: [Section], animated: Bool = true, requiresIsolatedProcess: Bool, completion: (() -> Void)? = nil) {
guard isViewLoaded else {
dataSource.sections = sections
return
Expand All @@ -459,7 +461,7 @@ extension ChatViewController: ChatControllerDelegate {
guard let self = self else {
return
}
self.processUpdates(with: sections, animated: animated, completion: completion)
self.processUpdates(with: sections, animated: animated, requiresIsolatedProcess: requiresIsolatedProcess, completion: completion)
})
currentInterfaceActions.add(reaction: reaction)
return
Expand All @@ -475,6 +477,10 @@ extension ChatViewController: ChatControllerDelegate {
return
}

if requiresIsolatedProcess {
chatLayout.processOnlyVisibleItemsOnAnimatedBatchUpdates = true
currentInterfaceActions.options.insert(.updatingCollectionInIsolation)
}
currentControllerActions.options.insert(.updatingCollection)
collectionView.reload(using: changeSet,
interrupt: { changeSet in
Expand All @@ -491,6 +497,10 @@ extension ChatViewController: ChatControllerDelegate {
},
completion: { _ in
DispatchQueue.main.async {
self.chatLayout.processOnlyVisibleItemsOnAnimatedBatchUpdates = false
if requiresIsolatedProcess {
self.currentInterfaceActions.options.remove(.updatingCollectionInIsolation)
}
completion?()
self.currentControllerActions.options.remove(.updatingCollection)
}
Expand Down Expand Up @@ -595,7 +605,7 @@ extension ChatViewController: InputBarAccessoryViewDelegate {
self.scrollToBottom(completion: {
self.chatController.sendMessage(.text(messageText)) { sections in
self.currentInterfaceActions.options.remove(.sendingMessage)
self.processUpdates(with: sections, animated: true)
self.processUpdates(with: sections, animated: true, requiresIsolatedProcess: false)
}
})
}
Expand Down
12 changes: 6 additions & 6 deletions Example/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
PODS:
- ChatLayout (1.2.13):
- ChatLayout/Ultimate (= 1.2.13)
- ChatLayout/Core (1.2.13)
- ChatLayout/Extras (1.2.13):
- ChatLayout (1.2.14):
- ChatLayout/Ultimate (= 1.2.14)
- ChatLayout/Core (1.2.14)
- ChatLayout/Extras (1.2.14):
- ChatLayout/Core
- ChatLayout/Ultimate (1.2.13):
- ChatLayout/Ultimate (1.2.14):
- ChatLayout/Core
- ChatLayout/Extras
- DifferenceKit (1.3.0):
Expand Down Expand Up @@ -35,7 +35,7 @@ EXTERNAL SOURCES:
:path: "../"

SPEC CHECKSUMS:
ChatLayout: c37e188edd9a922d4c19d259703a29c63e0d18c6
ChatLayout: 0dabcfbceffa95f2a9a11c3bed1439457f89bc77
DifferenceKit: ab185c4d7f9cef8af3fcf593e5b387fb81e999ca
FPSCounter: 884afec377de66637808c4f52ecc3b85a404732b
InputBarAccessoryView: 1d7b0a672b36e370f01f264b3907ef39d03328e3
Expand Down
2 changes: 2 additions & 0 deletions Example/Tests/MockCollectionLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class MockCollectionLayout: ChatLayoutRepresentation, ChatLayoutDelegate {

let keepContentOffsetAtBottomOnBatchUpdates: Bool = true

let processOnlyVisibleItemsOnAnimatedBatchUpdates: Bool = true

func numberOfItems(in section: Int) -> Int {
numberOfItemsInSection[section] ?? 0
}
Expand Down
4 changes: 2 additions & 2 deletions docs/Classes/CellLayoutContainerView.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<header class="header">
<p class="header-col header-col--primary">
<a class="header-link" href="../index.html">
ChatLayout 1.2.13 Docs
ChatLayout 1.2.14 Docs
</a>
(100% documented)
</p>
Expand Down Expand Up @@ -455,7 +455,7 @@ <h4>Parameters</h4>
</article>
</div>
<section class="footer">
<p>&copy; 2022 <a class="link" href="https:/ekazaev" target="_blank" rel="external noopener">Evgeny Kazaev</a>. All rights reserved. (Last updated: 2022-11-02)</p>
<p>&copy; 2022 <a class="link" href="https:/ekazaev" target="_blank" rel="external noopener">Evgeny Kazaev</a>. All rights reserved. (Last updated: 2022-11-04)</p>
<p>Generated by <a class="link" href="https:/realm/jazzy" target="_blank" rel="external noopener">jazzy ♪♫ v0.14.3</a>, a <a class="link" href="https://realm.io" target="_blank" rel="external noopener">Realm</a> project.</p>
</section>
</body>
Expand Down
4 changes: 2 additions & 2 deletions docs/Classes/ChatLayoutAttributes.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<header class="header">
<p class="header-col header-col--primary">
<a class="header-link" href="../index.html">
ChatLayout 1.2.13 Docs
ChatLayout 1.2.14 Docs
</a>
(100% documented)
</p>
Expand Down Expand Up @@ -414,7 +414,7 @@ <h4>Declaration</h4>
</article>
</div>
<section class="footer">
<p>&copy; 2022 <a class="link" href="https:/ekazaev" target="_blank" rel="external noopener">Evgeny Kazaev</a>. All rights reserved. (Last updated: 2022-11-02)</p>
<p>&copy; 2022 <a class="link" href="https:/ekazaev" target="_blank" rel="external noopener">Evgeny Kazaev</a>. All rights reserved. (Last updated: 2022-11-04)</p>
<p>Generated by <a class="link" href="https:/realm/jazzy" target="_blank" rel="external noopener">jazzy ♪♫ v0.14.3</a>, a <a class="link" href="https://realm.io" target="_blank" rel="external noopener">Realm</a> project.</p>
</section>
</body>
Expand Down
4 changes: 2 additions & 2 deletions docs/Classes/ChatLayoutInvalidationContext.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<header class="header">
<p class="header-col header-col--primary">
<a class="header-link" href="../index.html">
ChatLayout 1.2.13 Docs
ChatLayout 1.2.14 Docs
</a>
(100% documented)
</p>
Expand Down Expand Up @@ -199,7 +199,7 @@ <h4>Declaration</h4>
</article>
</div>
<section class="footer">
<p>&copy; 2022 <a class="link" href="https:/ekazaev" target="_blank" rel="external noopener">Evgeny Kazaev</a>. All rights reserved. (Last updated: 2022-11-02)</p>
<p>&copy; 2022 <a class="link" href="https:/ekazaev" target="_blank" rel="external noopener">Evgeny Kazaev</a>. All rights reserved. (Last updated: 2022-11-04)</p>
<p>Generated by <a class="link" href="https:/realm/jazzy" target="_blank" rel="external noopener">jazzy ♪♫ v0.14.3</a>, a <a class="link" href="https://realm.io" target="_blank" rel="external noopener">Realm</a> project.</p>
</section>
</body>
Expand Down
37 changes: 35 additions & 2 deletions docs/Classes/CollectionViewChatLayout.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<header class="header">
<p class="header-col header-col--primary">
<a class="header-link" href="../index.html">
ChatLayout 1.2.13 Docs
ChatLayout 1.2.14 Docs
</a>
(100% documented)
</p>
Expand Down Expand Up @@ -165,6 +165,8 @@ <h3 id='custom-properties' class='heading'>Custom Properties:</h3>

<p><code><a href="../Classes/CollectionViewChatLayout.html#/s:10ChatLayout014CollectionViewaB0C39keepContentOffsetAtBottomOnBatchUpdatesSbvp">CollectionViewChatLayout.keepContentOffsetAtBottomOnBatchUpdates</a></code></p>

<p><code><a href="../Classes/CollectionViewChatLayout.html#/s:10ChatLayout014CollectionViewaB0C45processOnlyVisibleItemsOnAnimatedBatchUpdatesSbvp">CollectionViewChatLayout.processOnlyVisibleItemsOnAnimatedBatchUpdates</a></code></p>

<p><code><a href="../Classes/CollectionViewChatLayout.html#/s:10ChatLayout014CollectionViewaB0C13visibleBoundsSo6CGRectVvp">CollectionViewChatLayout.visibleBounds</a></code></p>

<p><code><a href="../Classes/CollectionViewChatLayout.html#/s:10ChatLayout014CollectionViewaB0C11layoutFrameSo6CGRectVvp">CollectionViewChatLayout.layoutFrame</a></code></p>
Expand Down Expand Up @@ -277,6 +279,37 @@ <h4>Declaration</h4>
</section>
</div>
</li>
<li class="item">
<div>
<code>
<a name="/s:10ChatLayout014CollectionViewaB0C45processOnlyVisibleItemsOnAnimatedBatchUpdatesSbvp"></a>
<a name="//apple_ref/swift/Property/processOnlyVisibleItemsOnAnimatedBatchUpdates" class="dashAnchor"></a>
<a class="token" href="#/s:10ChatLayout014CollectionViewaB0C45processOnlyVisibleItemsOnAnimatedBatchUpdatesSbvp">processOnlyVisibleItemsOnAnimatedBatchUpdates</a>
</code>
</div>
<div class="height-container">
<div class="pointer-container"></div>
<section class="section">
<div class="pointer"></div>
<div class="abstract">
<p>tries to process only the elements that are currently visible on the screen. But often it is not needed. This flag allows you to have fine control over this behaviour.
It set to <code>true</code> by default to keep the compatibility with the older versions of the library.</p>

<p><strong>NB:</strong>
This flag is only to provide fine control over the batch updates. If in doubts - keep it <code>true</code>.</p>

</div>
<div class="declaration">
<h4>Declaration</h4>
<div class="language">
<p class="aside-title">Swift</p>
<pre class="highlight swift"><code><span class="kd">public</span> <span class="k">var</span> <span class="nv">processOnlyVisibleItemsOnAnimatedBatchUpdates</span><span class="p">:</span> <span class="kt">Bool</span></code></pre>

</div>
</div>
</section>
</div>
</li>
<li class="item">
<div>
<code>
Expand Down Expand Up @@ -1306,7 +1339,7 @@ <h4>Declaration</h4>
</article>
</div>
<section class="footer">
<p>&copy; 2022 <a class="link" href="https:/ekazaev" target="_blank" rel="external noopener">Evgeny Kazaev</a>. All rights reserved. (Last updated: 2022-11-02)</p>
<p>&copy; 2022 <a class="link" href="https:/ekazaev" target="_blank" rel="external noopener">Evgeny Kazaev</a>. All rights reserved. (Last updated: 2022-11-04)</p>
<p>Generated by <a class="link" href="https:/realm/jazzy" target="_blank" rel="external noopener">jazzy ♪♫ v0.14.3</a>, a <a class="link" href="https://realm.io" target="_blank" rel="external noopener">Realm</a> project.</p>
</section>
</body>
Expand Down
4 changes: 2 additions & 2 deletions docs/Classes/ContainerCollectionReusableView.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<header class="header">
<p class="header-col header-col--primary">
<a class="header-link" href="../index.html">
ChatLayout 1.2.13 Docs
ChatLayout 1.2.14 Docs
</a>
(100% documented)
</p>
Expand Down Expand Up @@ -375,7 +375,7 @@ <h4>Parameters</h4>
</article>
</div>
<section class="footer">
<p>&copy; 2022 <a class="link" href="https:/ekazaev" target="_blank" rel="external noopener">Evgeny Kazaev</a>. All rights reserved. (Last updated: 2022-11-02)</p>
<p>&copy; 2022 <a class="link" href="https:/ekazaev" target="_blank" rel="external noopener">Evgeny Kazaev</a>. All rights reserved. (Last updated: 2022-11-04)</p>
<p>Generated by <a class="link" href="https:/realm/jazzy" target="_blank" rel="external noopener">jazzy ♪♫ v0.14.3</a>, a <a class="link" href="https://realm.io" target="_blank" rel="external noopener">Realm</a> project.</p>
</section>
</body>
Expand Down
Loading

0 comments on commit 3743433

Please sign in to comment.