From f4a3261866cbbe97c1cd6b190ac1438d4ed3313f Mon Sep 17 00:00:00 2001 From: Benoit Martins Date: Thu, 23 Feb 2023 10:12:26 +0100 Subject: [PATCH] BubbleChat UI updates --- .../ChatConversationTableViewSwift.swift | 62 +++++++++++----- .../Chat/Views/MultilineMessageCell.swift | 73 +++++++++++-------- .../Util/BackActionsNavigationView.swift | 31 +++++++- 3 files changed, 114 insertions(+), 52 deletions(-) diff --git a/Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift b/Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift index f771ebaaf..14f6058ca 100644 --- a/Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift +++ b/Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift @@ -17,7 +17,44 @@ let textExample = [ "Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam nibh. Mauris ac mauris sed pede pellentesque fermentum. Maecenas adipiscing", "Lorem ipsum dolor sit amet", "Salut Salut Salut", - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut in risus volutpat libero pharetra tempor. Cras vestibulum bibendum augue. Praesent egestas leo in pede. Praesent blandit odio eu enim. Pellentesque sed dui ut augue blandit sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam nibh. Mauris ac mauris sed pede pellentesque fermentum. Maecenas adipiscing ante non diam sodales hendrerit." + "Salut", + "1", + "Oui", + "test", + "Salut", + "Salut", + "1", + "Oui", + "test", + "Salut", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut in risus volutpat libero pharetra tempor. Cras vestibulum bibendum augue. Praesent egestas leo in pede. Praesent blandit odio eu enim. Pellentesque sed dui ut augue blandit sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam nibh. Mauris ac mauris sed pede pellentesque fermentum. Maecenas adipiscing ante non diam sodales hendrerit.", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper.", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper." +] + +let messageExample : [Int] = [ + 0, + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 1, + 0, + 1, + 1, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 1, + 0 ] class ChatConversationTableViewSwift: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { @@ -39,40 +76,31 @@ class ChatConversationTableViewSwift: UIViewController, UICollectionViewDataSour override func viewDidLoad() { super.viewDidLoad() - // Register Cells collectionView.register(MultilineMessageCell.self, forCellWithReuseIdentifier: MultilineMessageCell.reuseId) - // Add `coolectionView` to display hierarchy and setup its appearance view.addSubview(collectionView) - collectionView.backgroundColor = .white + collectionView.backgroundColor = VoipTheme.backgroundWhiteBlack.get() collectionView.contentInsetAdjustmentBehavior = .always collectionView.contentInset = UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0) - // Setup Autolayout constraints collectionView.translatesAutoresizingMaskIntoConstraints = false collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true collectionView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true collectionView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true collectionView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true - // Setup `dataSource` and `delegate` collectionView.dataSource = self collectionView.delegate = self (collectionView.collectionViewLayout as! UICollectionViewFlowLayout).estimatedItemSize = UICollectionViewFlowLayout.automaticSize - (collectionView.collectionViewLayout as! UICollectionViewFlowLayout).minimumLineSpacing = 1 + (collectionView.collectionViewLayout as! UICollectionViewFlowLayout).minimumLineSpacing = 2 + + UIDeviceBridge.displayModeSwitched.readCurrentAndObserve { _ in + self.collectionView.backgroundColor = VoipTheme.backgroundWhiteBlack.get() + } } override func viewDidAppear(_ animated: Bool) { - /* - DispatchQueue.main.async { - for i in 1...100{ - let indexPath = IndexPath(row: self.collectionViewMessageItem.count, section: 0) - self.collectionViewMessageItem.append(i) - self.collectionViewMessage.insertItems(at: [indexPath]) - } - } - */ //let bottomOffset = CGPoint(x: 0, y: collectionView.contentSize.height) //collectionView.setContentOffset(bottomOffset, animated: false) } @@ -80,7 +108,7 @@ class ChatConversationTableViewSwift: UIViewController, UICollectionViewDataSour // MARK: - UICollectionViewDataSource - func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MultilineMessageCell.reuseId, for: indexPath) as! MultilineMessageCell - cell.configure(text: textExample[indexPath.row]) + cell.configure(text: textExample[indexPath.row], mess: messageExample[indexPath.row]) return cell } diff --git a/Classes/Swift/Chat/Views/MultilineMessageCell.swift b/Classes/Swift/Chat/Views/MultilineMessageCell.swift index e43a0bd10..64149ae3d 100644 --- a/Classes/Swift/Chat/Views/MultilineMessageCell.swift +++ b/Classes/Swift/Chat/Views/MultilineMessageCell.swift @@ -13,29 +13,31 @@ class MultilineMessageCell: UICollectionViewCell { private let label: UILabel = UILabel(frame: .zero) private let contentBubble: UIView = UIView(frame: .zero) private let bubble: UIView = UIView(frame: .zero) + private let imageUser: UIView = UIView(frame: .zero) + private let chatRead = UIImageView(image: UIImage(named: "chat_read.png")) + var constraint1 : NSLayoutConstraint? = nil + var constraint2 : NSLayoutConstraint? = nil override init(frame: CGRect) { super.init(frame: frame) - let randomMessage = Int.random(in: 1..<3) - let labelInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) contentView.addSubview(contentBubble) - contentView.backgroundColor = .orange contentBubble.translatesAutoresizingMaskIntoConstraints = false contentBubble.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0).isActive = true contentBubble.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0).isActive = true - //contentBubble.width(UIScreen.main.bounds.size.width).done() - if(randomMessage == 1){ - contentBubble.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 50).isActive = true - }else{ - - } - //contentBubble.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 50).isActive = true - contentBubble.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20).isActive = true - - //contentBubble.backgroundColor = .green + constraint1 = contentBubble.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 40) + constraint2 = contentBubble.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -22) + constraint1!.isActive = true + + contentBubble.addSubview(imageUser) + imageUser.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true + imageUser.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 6).isActive = true + imageUser.backgroundColor = UIColor("D").withAlphaComponent(0.2) + imageUser.layer.cornerRadius = 15.0 + imageUser.size(w: 30, h: 30).done() + imageUser.isHidden = true contentBubble.addSubview(bubble) bubble.translatesAutoresizingMaskIntoConstraints = false @@ -44,11 +46,7 @@ class MultilineMessageCell: UICollectionViewCell { bubble.leadingAnchor.constraint(equalTo: contentBubble.leadingAnchor, constant: labelInset.left).isActive = true bubble.trailingAnchor.constraint(equalTo: contentBubble.trailingAnchor, constant: labelInset.right).isActive = true - //bubble.bounds.origin = contentView.bounds.origin - bubble.layer.cornerRadius = 10.0 - bubble.backgroundColor = .systemBlue - label.numberOfLines = 0 label.lineBreakMode = .byWordWrapping @@ -60,33 +58,44 @@ class MultilineMessageCell: UICollectionViewCell { label.leadingAnchor.constraint(equalTo: contentBubble.leadingAnchor, constant: labelInset.left+10).isActive = true label.trailingAnchor.constraint(equalTo: contentBubble.trailingAnchor, constant: labelInset.right-10).isActive = true + contentBubble.addSubview(chatRead) + chatRead.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -2).isActive = true + chatRead.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8).isActive = true + chatRead.size(w: 10, h: 10).done() + chatRead.isHidden = true } required init?(coder aDecoder: NSCoder) { fatalError("Storyboards are quicker, easier, more seductive. Not stronger then Code.") } - func configure(text: String?) { + func configure(text: String?, mess: Int) { label.text = text + print("Storyboards are quicker \(mess)") + if mess == 1 { + constraint1?.isActive = true + constraint2?.isActive = false + imageUser.isHidden = false + bubble.backgroundColor = UIColor("D").withAlphaComponent(0.2) + chatRead.isHidden = true + }else{ + constraint1?.isActive = false + constraint2?.isActive = true + imageUser.isHidden = true + bubble.backgroundColor = UIColor("A").withAlphaComponent(0.2) + chatRead.isHidden = false + } } override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { - //bubble.transform = CGAffineTransformIdentity - label.preferredMaxLayoutWidth = (UIScreen.main.bounds.size.width*4/5) - - //print("MultilineMessageCell init UIScreen label \(label.preferredMaxLayoutWidth)") + label.preferredMaxLayoutWidth = (UIScreen.main.bounds.size.width*3/4) layoutAttributes.bounds.size.height = systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height - layoutAttributes.bounds.size.width = (UIScreen.main.bounds.size.width / CGFloat(1)).rounded(.down) - //print("MultilineMessageCell init UIScreen \(UIScreen.main.bounds.size.width*4/5)") - //print("MultilineMessageCell init layoutAttributes \(layoutAttributes.bounds.size.width)") - //print("MultilineMessageCell init \((UIScreen.main.bounds.size.width*4/5) - layoutAttributes.bounds.size.width)") - - //For Left - //bubble.transform = CGAffineTransformTranslate(bubble.transform, (layoutAttributes.bounds.size.width - (UIScreen.main.bounds.size.width*4/5))/2, 0.0) - - //For Right - //bubble.transform = CGAffineTransformTranslate(bubble.transform, -(layoutAttributes.bounds.size.width - (UIScreen.main.bounds.size.width*4/5))/2, 0.0) + let cellsPerRow = 1 + let minimumInterItemSpacing = 1.0 + let marginsAndInsets = window!.safeAreaInsets.left + window!.safeAreaInsets.right + minimumInterItemSpacing * CGFloat(cellsPerRow - 1) + layoutAttributes.bounds.size.width = ((window!.bounds.size.width - marginsAndInsets) / CGFloat(cellsPerRow)).rounded(.down) + return layoutAttributes } } diff --git a/Classes/Swift/Util/BackActionsNavigationView.swift b/Classes/Swift/Util/BackActionsNavigationView.swift index 968c6eb0f..a5eedc2e9 100644 --- a/Classes/Swift/Util/BackActionsNavigationView.swift +++ b/Classes/Swift/Util/BackActionsNavigationView.swift @@ -76,6 +76,8 @@ class BackActionsNavigationView: UIViewController { var isSecure : Bool = false var isGroupChat : Bool = false let floatingButton = CallControlButton(buttonTheme:VoipTheme.nav_button("")) + var constraintFloatingButton : NSLayoutConstraint? = nil + var constraintLandscapeFloatingButton : NSLayoutConstraint? = nil var stackView = UIStackView() var stackViewReply = UIStackView() @@ -268,10 +270,17 @@ class BackActionsNavigationView: UIViewController { view.addSubview(stackView) view.addSubview(floatingButton) - floatingButton.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -1).isActive = true - floatingButton.topAnchor.constraint(equalTo: self.view.layoutMarginsGuide.topAnchor, constant: top_bar_height + 4).isActive = true + constraintFloatingButton = floatingButton.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 3) + constraintLandscapeFloatingButton = floatingButton.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -56) + if UIDevice.current.orientation.isLandscape { + constraintLandscapeFloatingButton!.isActive = true + } else { + constraintFloatingButton!.isActive = true + } + constraintFloatingButton!.isActive = true + floatingButton.topAnchor.constraint(equalTo: self.view.layoutMarginsGuide.topAnchor, constant: top_bar_height).isActive = true floatingButton.setImage(UIImage(named:"security_alert_indicator.png"), for: .normal) - floatingButton.imageEdgeInsets = UIEdgeInsets(top: 45, left: 45, bottom: 45, right: 45) + floatingButton.imageEdgeInsets = UIEdgeInsets(top: 42, left: 42, bottom: 42, right: 42) floatingButton.onClickAction = action3 stackView.centerXAnchor.constraint(equalTo:self.view.centerXAnchor).isActive = true @@ -289,6 +298,8 @@ class BackActionsNavigationView: UIViewController { self.recordingWaveView.backgroundColor = VoipTheme.backgroundWhiteBlack.get() self.recordingWaveImageMask.backgroundColor = VoipTheme.backgroundWhiteBlack.get() } + + NotificationCenter.default.addObserver(self, selector: #selector(self.rotated), name: UIDevice.orientationDidChangeNotification, object: nil) } override func viewWillAppear(_ animated: Bool) { @@ -296,6 +307,20 @@ class BackActionsNavigationView: UIViewController { topBar.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() } + deinit { + NotificationCenter.default.removeObserver(self) + } + + @objc func rotated() { + if UIDevice.current.orientation.isLandscape { + constraintLandscapeFloatingButton!.isActive = true + constraintFloatingButton!.isActive = false + } else { + constraintLandscapeFloatingButton!.isActive = false + constraintFloatingButton!.isActive = true + } + } + func changeTitle(titleString: String){ titleLabel.text = titleString titleGroupLabel.text = titleString