ChatLayout icon indicating copy to clipboard operation
ChatLayout copied to clipboard

Include replica of iMessage curved lines connecting replies

Open ElrB opened this issue 1 year ago • 1 comments

Hi @ekazaev

I have tried to implement the solution you pointed out in the last issue, but without any good outcome. Below I will add screenshot of how I have went on to implement the solution and results.

New variables in MainContainerView class: Screenshot 2024-02-08 at 7 18 07 PM

  • setupSubviews() Screenshot 2024-02-08 at 7 20 50 PM

  • updateContainerView() & resetContainerView() Screenshot 2024-02-08 at 7 22 08 PM

  • CurvedLineView Screenshot 2024-02-08 at 7 23 03 PM

  • Data source createTextCell (here I check if message is a reply so that curve line view can be created or not) Screenshot 2024-02-08 at 7 23 51 PM

Results:

It seems like the width of the line is just off, even if I try get the width of the bubble view then subtract it from the screen size so that I get get the remaining width that the bubble view is not occupying. When I scroll, weird behaviours start occurring with the curve line, it starts changing in width and height size, affect the bubble view size as well. The weird behaviours make me think if reuse of cells without clearing the curved line is the cause, but not sure.

Unexpected result marked with red, expected result marked with blue.

image_6487327-3 image_6487327-4 image_6487327-5

Please help. Thanks.

ElrB avatar Feb 08 '24 17:02 ElrB

@ElrB Unfortunately I cant write code for you. I can give you only some directions. It looks like you are on the right path but I cant sit and debug your code. I am sorry.

If I can suggest something: take constraints from the layout like TextMessageView does

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

Pass it somehow (create a multiple delegate listener for example) and pass it up to the all views that might be interested. In your example It is unclear why do you set up width to 310. Iphones have different screen sizes.

Here it seems that the cell is not handling reuse properly. Because there is no reply in the previous cell. Screenshot 2024-02-08 at 20 56 31

I see you decided not to move the reply bubble into the message bubble. That means that you also need to pass somehow the information where is the reply in the previous cell is positioned and act accordingly. I am also not sure how you are going to handle the situation is the reply bubble is short. Even if the curve will work correctly it will point into the void, not the best visual decision imho.

That is as much as I can help you unfortunately. It hard to look at the code without an ability to put a breakpoint and check the constraints and values.

Keep trying.

Best of luck.

ekazaev avatar Feb 08 '24 20:02 ekazaev

Hi @ekazaev

I will leave this route, and take the WhatsApp reply style. I just have one question or seek your last help then we can close the issue.

Right now I see bubble view is create like; let bubbleView = cell.customView.customView.customView in the createCell methods.

How can I create a BezierMaskedView<CustomView> (message bubble view) without having to dequeue/initialise a cell?

Additionally, I have made a change in TextMessageView: added the below in setupSize()

if message.messageCoreInformation.isReply { textView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: replyViewHeight).isActive = true } else { textView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true } setNeedsLayout()

The constraints are fine on first chat load up, but when I start scrolling some reply bubbles' top anchor constant is not as was before, it becomes zero like the non reply bubbles. I tried inactivating top anchor in reuse but didn't resolve the issue. It is also not the issue of message suddenly making .messageCoreInformation.isReply = false, message is provided by the text message controller.

Thanks.

ElrB avatar Feb 10 '24 17:02 ElrB

@ElrB

How can I create a BezierMaskedView (message bubble view) without having to dequeue/initialise a cell?

Do you mean like this?

let view =  BezierMaskedView<UIView>(frame: CGRect(origin: .zero, size: .init(width: 300, height: 50)))
view.customView.backgroundColor = .green
Screenshot 2024-02-12 at 14 26 11

Additionally, I have made a change in TextMessageView: added the below in setupSize()

The second I do not understand. I need to see the code to try. Fork the example app, modify it and Ill have a look.

But I suggest you to use an extra container view rather than modifying the TextMessageView. I a similar way like I added an extra stack view in the container in your previous question. It should give you more flexibility.

ekazaev avatar Feb 12 '24 14:02 ekazaev

Hi @ekazaev

Thanks for answering the first part. Feel a bit dumb now :D

For the second part. Try add a constant for the text view top anchor like in below image, then scroll the chat up and down. The constraints are not consistent after scrolling. I want to push the text view down so that I can make space to add the reply message view. I tried activating the top anchor constraint in reloadData method but issue was still there.

Screenshot 2024-02-12 at 6 30 03 PM

ElrB avatar Feb 12 '24 16:02 ElrB

@ElrB I do not see such behaviour. Everything is as expected.

Screenshot 2024-02-12 at 17 06 42
diff --git a/Example/ChatLayout/Chat/View/Text Message View/TextMessageView.swift b/Example/ChatLayout/Chat/View/Text Message View/TextMessageView.swift
index c9a704f..6d226fb 100644
--- a/Example/ChatLayout/Chat/View/Text Message View/TextMessageView.swift	
+++ b/Example/ChatLayout/Chat/View/Text Message View/TextMessageView.swift	
@@ -23,6 +23,7 @@ final class TextMessageView: UIView, ContainerCollectionViewCellDelegate {
     private var controller: TextMessageController?
 
     private var textViewWidthConstraint: NSLayoutConstraint?
+    private var textViewTopConstraint: NSLayoutConstraint?
 
     override init(frame: CGRect) {
         super.init(frame: frame)
@@ -74,7 +75,8 @@ final class TextMessageView: UIView, ContainerCollectionViewCellDelegate {
         guard let controller else {
             return
         }
-        textView.text = controller.text
+        textView.text = "\(controller.text.count % 2 == 0 ? "[Odd]" : "[Even]") \(controller.text)"
+        setupSize()
         UIView.performWithoutAnimation {
             if #available(iOS 13.0, *) {
                 textView.textColor = controller.type.isIncoming ? UIColor.label : .systemBackground
@@ -112,18 +114,25 @@ final class TextMessageView: UIView, ContainerCollectionViewCellDelegate {
         textView.font = UIFont.preferredFont(forTextStyle: .body)
         addSubview(textView)
         NSLayoutConstraint.activate([
-            textView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor),
             textView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor),
             textView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
             textView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor)
         ])
+        textViewTopConstraint = textView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: 80)
+        textViewTopConstraint?.priority = UILayoutPriority(rawValue: 999)
         textViewWidthConstraint = textView.widthAnchor.constraint(lessThanOrEqualToConstant: viewPortWidth)
         textViewWidthConstraint?.isActive = true
+        textViewTopConstraint?.isActive = true
     }
 
     private func setupSize() {
         UIView.performWithoutAnimation {
             self.textViewWidthConstraint?.constant = viewPortWidth * Constants.maxWidth
+            if (controller?.text.count ?? 0) % 2 == 0 {
+                textViewTopConstraint?.constant = 80
+            } else {
+                textViewTopConstraint?.constant = 0
+            }
             setNeedsLayout()
         }
     }

ekazaev avatar Feb 12 '24 17:02 ekazaev

Thanks @ekazaev I think am good to finish coding replies now.

ElrB avatar Feb 12 '24 18:02 ElrB