GithubHelp home page GithubHelp logo

ekazaev / chatlayout Goto Github PK

View Code? Open in Web Editor NEW
805.0 16.0 64.0 17.32 MB

ChatLayout is an alternative solution to MessageKit. It uses custom UICollectionViewLayout to provide you full control over the presentation as well as all the tools available in UICollectionView. It supports dynamic cells and supplementary view sizes.

License: MIT License

Ruby 0.42% Swift 99.58%
chat chat-application messaging messenger uicollectionviewlayout collectionview collectionviewlayout swift uicollectionview custom-uicollectionviewlayout

chatlayout's People

Contributors

ekazaev avatar heoblitz avatar mehrankmlf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chatlayout's Issues

Audio message

Hi, will you consider adding audio messages to the example?

PDF cells

Hi ekazaev,

Can you kindly add pdf cells to example app. Small gift to us for 2024 πŸ˜‰. It has been hard to do using MessageKit, but I think with the flexibility of ChatLayout, it’s pretty doable, but want your way. Thanks.

ChatLayout paging

Hello!
I want to use ChatLayout in my project, however I met some difficulties with it.
There is a problem with a chat that contains over 5000 messages: scrolling animation is freezing and FPS is decreasing. So I want to make paging: add messages to the edge of scroll and delete from another edge. Insertion has good behavior whereas deletion has scrolling animation (which is good for visible area, but it is expected that position of cell remain the same during deletion beyond visible area). I tried to disable animation when there is deletion outside of visible area, unfortunately I couldn't. Could you suggest methods to do that kind of changes?

Cells are not positioned right/left without chatLayout.invalidateLayout()

@ekazaev thanks for such amazing project, I do not regret taking the time to study it.

I tried to solve the question why it happens that the cells after scrolling do not take into account their right / left position, this seems to be solved by periodically calling chatLayout.invalidateLayout() by timer, but this is not a solution.

As a basis, I took a simplified version from the sample application. I have attached a video showing this problem.
https://youtube.com/shorts/xfzyfh8v2Ps?feature=share

Seems to be related to this piece of code, but your help is needed. Thanks

cellView.leadingView?.isHiddenSafe = !alignment.isIncoming
cellView.leadingView?.alpha = alignment.isIncoming ? 1 : 0
cellView.trailingView?.isHiddenSafe = alignment.isIncoming
cellView.trailingView?.alpha = alignment.isIncoming ? 0 : 1

General Question UITableView vs UICollectionView

Hi,
I read your blog post about how you managed to create this Library. I am not fully convinced why someone should use UICollectionView instead of UITableVIew. I know UICollectionView has more features & power to customise e.t.c. But I would really like your opinion why someone should use UICollectionView instead of UITableView which handles very nice the autolayout calculations.

Messages are pushed up when keyboard appears

Messages are pushed up when keyboard appears creating a gab between last message and keyboard, however there is space available.

Image without keyboard showing the screen has enough space:

without keyboard

Image with keyboard appearing showing the gap:

with keyboard

NSInternalInconsistencyException

Hi, thank u for the new chat behaviour.

I faced with crash on your example app, you can reproduce it, if replace your code in DefaultChatController

Reason: invalid number of sections. The number of sections contained in the collection view after the update (170) must be equal to the number of sections contained in the collection view before the update (89), plus or minus the number of sections inserted or deleted (0 inserted, 1 deleted).

change line 147

DispatchQueue.main.async { [weak self] in
    guard self != nil else {
        return
    }
    completion([Section(id: 0, title: "Loading...", cells: Array(cells))])
}

to

DispatchQueue.main.async { [weak self] in
    guard self != nil else {
        return
    }

    let sections = Array(cells).map { cell in
        Section(id: cell.differenceIdentifier, title: "New Section", cells: [cell])
    }

    completion(sections)
}

Translation button break the UI

On iOS15 Apple added a new Translate button in the uiMenuController.
Step to reproduce:
Select the text from the input bar and click to translate, then close the bottom sheet
Result: The ChatViewController will scroll up and the input bar will be removed:
translation

Bottom offset keeping issues

Hi @ekazaev and thanks for the great chat layout solution!

I'm facing the issue with keeping collection view content at bottom position. Given restoreContentOffset in UIView.animate block makes top cells disappear like on the video below.

111111.mp4

I was able to fix this behaviour by trying scrollRectToVisible, scrollToItem and setContentOffset (they give same result). Now top cells are not disappearing but if collection isn't at bottom position when batch updates starts it scrolls to bottom item for its estimated height only:

Screen.Recording.2023-07-13.at.16.07.40.mov

I saw similar issues in this repo but there was no solution for my case. Can you help me to figure it out?

keepContentOffsetAtBottomOnBatchUpdates add tolerance range

Hello @ekazaev πŸ‘‹ Currently, the layout only scrolls automatically when you have scrolled all the way down. Can you add a configuration for a tolerance range? So that even if you are for example 100pt from the bottom of the Scrollview and a new message comes in, it still scrolls automatically?

How to make collectioview show messages immediately

What needs to be done so that when the chatviewcontroller push-navigates, the data is already ready?

An empty collection is shown. then messages? Like no spawn animation.

i played with it

collectionView.contentInsetAdjustmentBehavior = .always

changed to this

collectionView.contentInsetAdjustmentBehavior = .never

then the collection of elements is loaded immediately

but there are a number of artifacts associated with tabbar navigation and inputAccessoryView

inputAccessoryView twitches and disappears and reappears 2 times

I attach screenshots

IMG_7545
IMG_7546
IMG_7547

please help me how to do this, thanks

What is the function of this code?

guard currentInterfaceActions.options.isEmpty else {
            print("A:\(Date())")
            let reaction = SetActor<Set<InterfaceActions>, ReactionTypes>.Reaction(type: .delayedUpdate,
                                                                                   action: .onEmpty,
                                                                                   executionType: .once,
                                                                                   actionBlock: { [weak self] in
                guard let self else {
                    return
                }
                print("B:\(Date())")
                processUpdates(with: sections, animated: animated, requiresIsolatedProcess: requiresIsolatedProcess, completion: completion)
                print("C:\(Date())")
            })
            currentInterfaceActions.add(reaction: reaction)
            return
        }

CollectionView does not scroll to last item when not visible item

Expected behaviour:
When a user sends a message and taps on the send button, the should be a scroll to the last item in the CollectionView.

Actual behaviour:
When a user sends a message and taps on the send button, the CollectionView will scroll to show the just top of the last item.

It appears to be taking the estimated item size instead of the actual size of the new cell that has just been sent by the end user. The cell is added to the view and can be seen once you manually scroll to the bottom. Example: when we increased the estimated item height to 100, the scrolling was correct, but only for smaller messages. If it was a bigger message, it would be cut off after 100 height.

Something to note is that the above behaviour occurs when animation = true when scrolling i.e. self?.collectionView.setContentOffset(contentOffsetAtBottom, animated: true). When animation = false the CollectionView will scroll to the correct position.

Reproduction steps:

  1. Open conversation
  2. Have at least enough messages where you can scroll up and not see the latest message
  3. Send a message while you are scrolled and can’t see the latest message
  4. See how it scrolls only to the top of the latest message not to the cell itself.

Note: scrollToBottom() is not currently working in the Example app provided

Correct way of layouting subviews

Hey @ekazaev!

I'm building a chat application on top of the Example project and trying to implement a view with following subviews (please see an attached image):

  1. Author label
  2. Image
  3. Reactions
  4. Date

These subviews are added as an arranged subview to a vertical UIStackView, which is added as a single subview to a let's call it MainView and used like TextMessageView or ImageView (in the example project). Another nuance is tapping on a reaction opens a reactions popup. Tapping a reaction on the popup leads to a new reaction on cell reactions, hence increasing the height and width of the cell in runtime.

Π‘onsidering things I said:

  1. Do you think using UIStackView the right way?
  2. What is the correct way of setting constraints where the cell has multiple views vertically and can increase dynamically?

As far as I understand I need to set the width (based on viewPortWidth) and height constraint of a subview in setupSize method, but in the example project all views (TextMessageView/ImageView/URLView) have only one subview. That's why I'm struggling with multiple vertical views.

Thank you! Let me know if you need any additional information.

example

Incorrect chat layout frame when running on iOS 17

Hello. πŸ™‚

We were running our existing app, that is built with Xcode 14.3, on iOS 17 to check for any bugs until we can switch to Xcode 15 and I noticed some weird behavior with the chat layout. When the sizeForItem delegate method is called, the chatLayout always has a width of 24. When running on iOS 16 it has the correct width of 366. I'm using the iPhone 14 for both scenarios. When building with Xcode 15 and running on iOS 17, there is no issue and we get the correct values.

I was curious if there might be something that I'm missing to try so that our builds using Xcode 14 will work correctly until we can start using Xcode 15?

Posting Image

Can we add an attachment button or camera button next to the input EditText so we can post photos?

Chat doesn't correctly scroll to bottom after receiving a new message on iOS 16

On iOS 16, the collection view doesn't correctly scroll to the bottom after receiving a new message.

Affected: All beta versions of iOS 16.

Expected Behavior

If the user is scrolled to the bottom of the collection view.
When they receive a new message
They collection view should scroll down to show the new message

Current Behavior

If the user is scrolled to the bottom of the collection view.
When they receive a new message
The collection view doesn't scroll

chat.layout.bug.mov

Possible Solution

Investigating, but no suggested fixes as of yet.

Steps to Reproduce

  1. Open the ChatLayout example on an iOS 16 simulator.
  2. Scroll to the bottom.
  3. Wait for new messages to arrive.
  4. Observe that they do not scroll to the correct item.

Context (Environment)

This leads to a broken experience on iOS 16.

Sticky headers

Hi! How we can implement sticky headers? It's not possible now?

AssertionFailure

image

Hey, first of all, good work with this library! πŸ™‚ I switched from MessageKit.

I use ChatLayout with RxDataSources and somehow every now and then I'm getting an assertion failure when adding a new message.

I have not yet looked at the layout in detail and wondered if you might know what the problem could be?

Image View Play Button Constraints

Hi,

I hope you are well.
In the example app's ImageView class, I try to create and add a play button to represent video messages, but I am struggling to constrain the play button image view in the centre of the bubble. Sometimes it appears in the centre, sometimes it doesn't (appears misplaced). I have copied the class' code below. Please assist in constraining the play button correctly. Thanks.

final class ImageView: UIView, ContainerCollectionViewCellDelegate {

private lazy var stackView = UIStackView(frame: bounds)

private lazy var loadingIndicator = UIActivityIndicatorView(style: .gray)

private lazy var imageView = UIImageView(frame: bounds)

private lazy var playButtonView = UIImageView()

private var controller: ImageController!

private var imageWidthConstraint: NSLayoutConstraint?

private var imageHeightConstraint: NSLayoutConstraint?

private var viewPortWidth: CGFloat = 300

override init(frame: CGRect) {
    super.init(frame: frame)
    setupSubviews()
}

required init?(coder: NSCoder) {
    super.init(coder: coder)
    setupSubviews()
}

func prepareForReuse() {
    imageView.image = nil
    playButtonView.isHidden = true
}

func apply(_ layoutAttributes: ChatLayoutAttributes) {
    viewPortWidth = layoutAttributes.layoutFrame.width
    setupSize()
}

// Uncomment to demonstrate the manual cell size calculation.
// NB: Keep in mind that the cell itself is still using autolayout to layout it content. If you really want to speed up the
// performance, You must layout the entire!!! `UICollectionCell` manually or using the tools
// like [LayoutKit](https://github.com/linkedin/LayoutKit)

// func preferredLayoutAttributesFitting(_ layoutAttributes: ChatLayoutAttributes) -> ChatLayoutAttributes? {
// viewPortWidth = layoutAttributes.layoutFrame.width
// switch controller.state {
// case .loading:
// layoutAttributes.frame.size.height = 100
// return layoutAttributes
// case let .image(image):
// let maxWidth = min(viewPortWidth * Constants.maxWidth, image.size.width)
// layoutAttributes.frame.size.height = image.size.height * maxWidth / image.size.width
// return layoutAttributes
// }
// }

func setup(with controller: ImageController) {
    self.controller = controller
}

func reloadData() {
    UIView.performWithoutAnimation {
        switch controller.state {
        case .loading:
            loadingIndicator.isHidden = false
            imageView.isHidden = true
            imageView.image = nil
            stackView.removeArrangedSubview(imageView)
            stackView.addArrangedSubview(loadingIndicator)
            if !loadingIndicator.isAnimating {
                loadingIndicator.startAnimating()
            }
            if #available(iOS 13.0, *) {
                backgroundColor = .systemGray5
            } else {
                backgroundColor = UIColor(red: 200 / 255, green: 200 / 255, blue: 200 / 255, alpha: 1)
            }
            setupSize()
        case let .image(image):
            loadingIndicator.isHidden = true
            loadingIndicator.stopAnimating()
            imageView.isHidden = false
            imageView.image = image
            stackView.removeArrangedSubview(loadingIndicator)
            stackView.addArrangedSubview(imageView)
            setupSize()
            backgroundColor = .clear
        }
        
        switch controller.imageType {
        case .videoThumb:
            playButtonView.isHidden = false
        case .image:
            playButtonView.isHidden = true
        }
    }
}

private func setupSubviews() {
    layoutMargins = .zero
    translatesAutoresizingMaskIntoConstraints = false
    insetsLayoutMarginsFromSafeArea = false

    addSubview(stackView)
    addSubview(playButtonView)
    stackView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        stackView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor),
        stackView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor),
        stackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
        stackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor)
    ])
    
    if #available(iOS 13.0, *) {
        playButtonView.image = UIImage(systemName: "play.circle.fill")
    }
    
    playButtonView.tintColor = .darkGray
    playButtonView.backgroundColor = .black
    playButtonView.contentMode = .scaleAspectFill
    playButtonView.layer.cornerRadius = 25
    playButtonView.bounds.size = CGSize(width: 50, height: 50)

    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.contentMode = .scaleAspectFill
    imageView.isHidden = true

    loadingIndicator.translatesAutoresizingMaskIntoConstraints = false
    loadingIndicator.isHidden = true
    
    let loadingWidthConstraint = loadingIndicator.widthAnchor.constraint(equalToConstant: 100)
    loadingWidthConstraint.priority = UILayoutPriority(999)
    loadingWidthConstraint.isActive = true

    let loadingHeightConstraint = loadingIndicator.heightAnchor.constraint(equalToConstant: 100)
    loadingHeightConstraint.priority = UILayoutPriority(999)
    loadingHeightConstraint.isActive = true

    imageWidthConstraint = imageView.widthAnchor.constraint(equalToConstant: 310)
    imageWidthConstraint?.priority = UILayoutPriority(999)

    imageHeightConstraint = imageView.heightAnchor.constraint(equalToConstant: 40)
    imageHeightConstraint?.priority = UILayoutPriority(999)
    playButtonView.center = center
}

private func setupSize() {
    UIView.performWithoutAnimation {
        switch controller.state {
        case .loading:
            imageWidthConstraint?.isActive = false
            imageHeightConstraint?.isActive = false
            playButtonView.center = center
            setNeedsLayout()
        case let .image(image):
            imageWidthConstraint?.isActive = true
            imageHeightConstraint?.isActive = true
            let maxWidth = min(viewPortWidth * Constants.maxWidth, image.size.width)
            imageWidthConstraint?.constant = maxWidth
            imageHeightConstraint?.constant = image.size.height * maxWidth / image.size.width
            playButtonView.center = center
            setNeedsLayout()
        }
    }
}

}

First message question

Hi!
How can I make it so that when I send the first and following messages in the chat, they are at the bottom of the screen?
Like Telegram, for example...
Simulator Screen Shot - iPhone 13 - 2022-04-22 at 16 19 04

Performance when push to ChatViewController not good

Hi @ekazaev!
I used to apply ChatLayout to my ChatViewController. When push from list conversations to ChatViewController screen, i think i have a problem. It seem a little slow to show messages in Chat screen. I have run Time Profile by Instruments. I don't know why there functions and classes get more time.

RPReplay_Final1685277349.MP4
image image

Preserving contentOffset bottom when keyboard show/hides using UICollectionViewController

Hello there,

Could you help me figuring out how to preserve the contentOffset from the bottom when the keyboard shows up or hides inside a UICollectionViewController? The example provided on the repo doesn't use a UICollectionVC so I figured you had to do all that keyboard listening etc. Without this I'm not being able to push the cells up along w/ the keyboard appearing. The content inset does change so on keyboard appearing I can scroll up and see the last cell but again it doesn't follow the keyboard. When the keyboard gets hidden it does though.

Thanks

iOS 15 multiple performBatchUpdates causes an animation problem

On the last release of the Chatlayout this issues was address but not really fixed.
In-fact in the example all actions are added one after the other. The way we use the library involves several changes at the same time.

Step to reproduce:
Have two different actions in the same operation like: remove a message and add a new one.
To simulate that I have updated the sendMessage function in DefaultChatController in line 63 by adding the following code:
if !messages.isEmpty { messages.removeLast() }

So now when you send a message it will delete the last message in the conversation at same time.
The StagedChangeset is a collection that now have two operations which involve two performBatchUpdates
Sep-30-2021 14-22-31

I'm opening this pull request to suggest a solution and open the discussion to that.
#21

question] position & scrolling

hello

After loading data, move to the "Read this far" cell. However, there is a phenomenon of tingling when scrolling from top to bottom after not going to the correct movement.

Conversely, there is no issue when scrolling from bottom to top after loading. I'll attach a video and some code, so please check it out, thank you.

celll is just created by autolayout

 var dataInput: [Section] {
        get { return data }
        set {
            let changeset = StagedChangeset(source: data, target: newValue)
            
            collectionView.reload(using: changeset) { data in
                self.data = data
            }
        }
    }
  collectionView.isPrefetchingEnabled = false
        collectionView.alwaysBounceVertical = true
        collectionView.automaticallyAdjustsScrollIndicatorInsets = true
        collectionView.translatesAutoresizingMaskIntoConstraints = false
 UIView.performWithoutAnimation {
            dataInput = changedData
        }

        if let index = scrollToIndexPath {
            collectionView.scrollToItem(at: index, at: .centeredVertically, animated: false)
// scroll to ReadToHear Item -> but not centered and somtimes not visible
        } else {
            collectionView.scrollToLast(animated: false)
        }

How to implement UICollectionView inside UICollectionViewCell right way?

          Hi @ekazaev. So sorry about reopening this issue. 

I had try to set new size of cell in function func preferredLayoutAttributesFitting(_ layoutAttributes: ChatLayoutAttributes) -> ChatLayoutAttributes?
But it still not working smooth. It's wrong in the first load. This is my code for UICollectionView in UICollectionViewCell
Please review and show to me my mistake.
Can you give me a tutorial project?
Thanks so much

SGIComponentActionView.swift.zip

Originally posted by @hhoangna in #44 (comment)

ChatLayout didn't expose sectionHeadersPinToVisibleBounds option

The ChatLayout is of type UICollectionViewLayout not UICollectionViewFlowLayout and I cannot set the layout.sectionHeadersPinToVisibleBounds = true

here is the code I used:

if let layout = chatCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
     layout.sectionHeadersPinToVisibleBounds = true
}

I need to set the section header sticky to the visible bounds.

Cannot installed with Carthage

Hi, team.
I'm trying to integrate the xcframework of this project via Carthage but it fails on command line compilation.

Please help me with this issue.

Xcode version 13.2 build issue

Hi bro,
I use Xcode 13.2 as a daily basis IDE. however, I met a compile error segmentation fault 11 for some files such as StateController line 675 columns 13. I've also realized that there is no Xcode backward compatibility. I've wondered so much as well.

Do you have any clue what's wrong with it?

Cells disappearing during layout animation

Hi! First of all, thank you for this wonderfully crafted library.

Now, I have an issue that has been haunting me for a long time both in my custom layouts and this ChatLayout. The issue is that during layout animations that would change the viewport of the collection view, the cells that would be out-of-screen by the end of the animation disappear immediately when animation begins. You can see it in the example app if you open the keyboard: cells at the top disappear as soon as the animation begins.

From what I could gather, this happens because the animations that are triggered by the layoutIfNeeded() call (used in restoreContentOffset method) are run out-of-process on the RenderServer and collection view has already done its layout pass by the time the animation begins, thus removing the cells.
There are some workarounds I thought of, like expanding the collection view frame beyond the top edge of the superview, or moving it with a transform, but these seem very hacky.
Have you ever encountered this issue and do you have any ideas on how to fix this?

Simulator.Screen.Recording.-.iPhone.14.-.2023-02-16.at.17.00.00.mp4

transitioning into the chat interface from the conversationList page is slow

Hello developer,

ChatLayout elegantly implements the layout of complex interfaces and offers smooth sliding. However, I've noticed that transitioning into the chat interface from the conversationList page is slow, even though the time taken to fetch data from the database is minimal.

Upon testing, I found that commenting out the line // KeyboardListener.shared.add(delegate: self) speeds up the display of the chat list. Alternatively, data displays quickly when pushing the conversationList controller with self.navigationController?.pushViewController(chatViewController, animated: false). But presenting the interface without animation feels awkward.

I've reviewed other issues such as:

#51
#40
Could you provide some optimization guidance?

Thank you.

RPReplay_Final1698737645.MP4

ChatViewController.swift.zip

Include replica of iMessage curved lines connecting replies

Hi @ekazaev

Do you mind including a replica in example app of how iMessage connect reply messages. Just a basic example of it.
Below is a screenshot from my app with blue line showing how I would like to draw the line. The app is based off the example app.

image_6487327

iMessage example:

jpeXf

Getting many prints of 'UICollectionViewRecursion' not sure what it means

Hello again! :)

I'm getting a lot of prints of the following message:
[UICollectionViewRecursion] cv == 0x7ff0518ece00 Disabling recursion trigger logging
But I have no idea what is it about. After a quick google search It seems related to compositional layout on iOS 15 maybe? Do you have any idea what is going on?

Just for sake of more clarity (if any) it prints when dequeueing the cells for the first time and all memory addresses are the same

Cheers!!

Keeping CollectionView at bottom when inserting any new message.

First off, Hats off for this amazing layout, I have always struggled with chat layouts due to weird bugs and unknown issues that happen during the development, but this layout has made my life 100x easier.

What I'm trying to achieve is to always keep the CollectionView at bottom when a new message is inserted.

I tried this code snippet

                self.collectionView.reload(using: stagedChangeSet) { messages in
                    self.messages = messages
                    self.collectionView.scrollToItem(at: IndexPath(item: messages.count - 1, section: 0), at: .bottom, animated: true)
                }

But it looks like it's not working and throwing this error

[UICollectionView] Warning: Invalid IndexPath <NSIndexPath: 0x9ece669de5d637ba> {length = 2, path = 0 - 6} specified - will use a contentOffset of {0,0} as a fallback value. <UICollectionView: 0x7fb7fd072400; frame = (0 0; 375 529); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x600001007720>; layer = <CALayer: 0x6000018633a0>; contentOffset: {0, 0}; contentSize: {374.99990000000003, 1412}; adjustedContentInset: {0, 0, 0, 0}; layout: <ChatLayout: 0x7fb7fcc25140>; dataSource: <ChatBotViewController: 0x7fb7faf35b20>>

Any idea what I'm doing wrong ?

Screen flickering when moving from landscape to portrait

Steps:

Send and receive messages
Move the phone to landscape
Move it back to portrait

Expected result:

Moving to portrait without flickering

Actual result:

Conversation flickers when moving to portrait

conversation.screen.flickering.MP4

How to implement UICollectionView inside UICollectionViewCell right way?

Hi @ekazaev! Thanks for your great pod. It's work perfect and very helpful with me
Everything is OK with custom view. But i have a problem when i make a custom view with UICollectionView auto layout inside.
I want to add a collectionview dynamic height inside and height off collectionview cell based on collectionview content height.
And the problem is the first load height of collectionview cell not correct. I need reload several times to get correct height of collectionview cell.
Please support me to get correct collection view height inside collectionview cell.

chat layout blinking

Hello.
There seems to be a bug that causes cells to blink in certain situations while using the chat layout.

Based on the sample app code provided, I tested it as follows (Tested after removing the automatically repopulate code)

Note:

  • keepContentOffsetAtBottomOnBatchUpdates must be set to true
  • Message in the first cell must be relatively short, and the text in the second message cell must be a relatively long message.
  • The first cell of the second section must be the same as the first cell of the first section.
let uuid = UUID()
let originMessage = Cell.message(.init(id: uuid, data: .text("short text message / shor text message / short text message / short text message / short text message / shor text message / short text message / short text message"), owner: User(id: 0), type.incoming), bubbleType: .normal)
let fristSectionModel = [Section(id: 0, title: "1", cells: [originMessage])]

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) { [weak self] in
    self?.processUpdates(with: fristSectionModel, animated: true, requiresIsolatedProcess: false)
}

let longMessage = Cell.message(.init(id: UUID(), data: .text("long text message / long text message / long text message / long text message / long text message / long text message / long text message / long text message / long text message / long text message / long text message/ long text message / long text message / long text message / long text message / long text message / long text message / long text message / long text message / long text message / long text message / long text message / long text message / long text message/ long text message / long text message / long text message / long text message / long text message / long text message / long text message / long text message"), ownerUser(id: 0), type: .incoming), bubbleType: .normal)
let secondSectionModel = [Section(id: 0, title: "1", cells: [originMessage, longMessage])]

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1000)) { [weak self] in
    self?.processUpdates(with: secondSectionModel, animated: true, requiresIsolatedProcess: false)
}

If you configure the code as above and build it, the first cell blinks as shown in the video below.
https://github.com/ekazaev/ChatLayout/assets/42825223/65fd8b4d-8505-43c3-ac3b-f6eb5ebc3388

When debugging, the public override func prepare(forCollectionViewUpdates updateItems: [UICollectionViewUpdateItem]) function is called and the state changes to .afterUpdate. When calculating the height of the controller, the state is calculated as the afterUpdate value, and the statement below becomes true and blinks.

 if heightDifference != 0,
           (keepContentOffsetAtBottomOnBatchUpdates && controller.contentHeight(at: state).rounded() + heightDifference > visibleBounds.height.rounded()) || isUserInitiatedScrolling,
           isAboveBottomEdge {
            context.contentOffsetAdjustment.y += heightDifference
            invalidationActions.formUnion([.shouldInvalidateOnBoundsChange])
        }

Please check this bug.
Thank you.

Section Headers/Footers are not animated along the cells (insert/update/delete)

Hi,

Im trying to integrate your ChatLayout library into an iOS project. At first, let me thank you for awesome job you did here.
Currently Im trying to structure the chat the way that:
Every message in the chat is represented as a single section in the collection view and read indicator is always shown under the latest message as a footer of the last message (section).

1. Self-sizing/autolayout issue:

Im using self-sizing cells, but I'm not sure if Im setting the correct value for estimatedSize. The self-sizing in this library works for any non-zero values, so eg setting the estimatedSize like following

collectionLayout.settings.estimatedItemSize = CGSize(width: 1, height: 1)

will display the cells, but at the same time will result in broken autolayout constraints

"<NSLayoutConstraint:0x600001d0e990 'UIView-Encapsulated-Layout-Height' UIView:0x7fdcbc40d8e0.height == 1   (active)>"

I wanted to use some general purpose estimatedSize for self-sizing cells, similar to the flow layout one:

UICollectionViewFlowLayout.automaticSize

but later realised since this is a custom collection view layout, this value is not declared.

Setting the estimated size to a concrete value, e.g. CGSize(width: 100, height: 30) will result in a treatment, where the cell's frame won't properly adjust as the content of the cell changes.
If you have any guidance here, Id really appreciate your help

2. Header/Footer are not part of the animation transaction
In my app, I want to treat the read indicator as a standalone item == not added as a subview in the cell, to gain better abstraction and to not pollute the cell with the standalone item.

Im including a sample SwiftUI app that leverages the ChatLayout - aim of this app is to showcase the issue #1 & #2.
ChatApp.zip

Any help highly appreciated!
Thanks!

Screen-Recording-2020-10-31-at-20 05 05

Weird update animation of the cell

Hey @ekazaev! Thanks for all the hard work you have done to make this thing work!
And without your Example app – we'd be lost as well. It is a huge source of inspiration and foundation to start building on.
I am yet founding my way around the library and all of the smart tricks you implement in example app.

There is one particular issue that I am facing right now when performing the updates, here is the demo:

Simulator.Screen.Recording.-.iPhone.12.-.2022-11-02.at.12.44.31.mp4

Reproduction steps:

  1. When user presses send button, message gets immediately added to the in-memory array of messages and they are propagated. Everything as like in your example app.
  2. At the same time message is send to the server (transport is not important, but for the sake of completeness it is websocket connection). It happens in the same method as adding to the in-memory array.
  3. After receiving the message server pings broadcasts back the freshly sent message back to the client. It has the same exact id, text and all other values except for date. Because server overrides the message timestamp with the newer one.
  4. Upon receiving this slightly updated message I call func received(messages: [RawMessage]), just as you did in example app.

And at this point I expect for the last message to just smoothly update its timestamp. But what happens the old version of cell jumps all the way to the top while fading away at the same time, and new message inserted from the bottom. You could see that from the video I attached.

CleanShot 2022-11-02 at 12 42 45

In the attached screenshot you can see the debugger breakpoint with corresponding prints of:

  • messages.last which is esentially the message that was appended to the in-memory array
  • rawMessages which is an array of size 1 of newly received messages from the server, which is the same message but with the updated timestamp. You can see that they have the same ids, and only the date is different.

I don't understand why the jump happens.

I hope that I explained my case with sufficient details. Let me know if I need to provide more input.

Huge bottom space and weird behavior for 1.1.11

Hi, some issues popped up with your lib. Up until 1.1.10 my app behaved fine, but as soon as I've upgraded ChatLayout to 1.1.11, things got flaky. When entering a chat room, a huge chunk of empty space without any chat message cells is shown. When looking into layout inspector, no cells show up within the collectionView. When scrolling up, some chat message cells appear, but when scrolling back down they start to disappear again. I first thought it is some autolayout issue (which it could still be), but it worked pre 1.1.11, so I thought I want to ask you here if you know what the issue could be.

trim 99C16C45-89F9-4ABF-98F9-6EC81DEFBCE1

Thank you, and it's a really cool library you have here!
Andreas

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.