From 6a6ea137f602ae67438da00496bbaee5347d1476 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Thu, 14 Jul 2022 16:40:06 +1000 Subject: [PATCH 01/12] update media message UI --- Podfile.lock | 2 +- .../Content Views/MediaView.swift | 2 + .../Message Cells/VisibleMessageCell.swift | 152 +++++++++--------- 3 files changed, 76 insertions(+), 80 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index 70045a1da..bab1ae426 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -232,4 +232,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 6ab902a81a379cc2c0a9a92c334c78d413190338 -COCOAPODS: 1.11.3 +COCOAPODS: 1.11.2 diff --git a/Session/Conversations/Message Cells/Content Views/MediaView.swift b/Session/Conversations/Message Cells/Content Views/MediaView.swift index a194e6588..da72fce47 100644 --- a/Session/Conversations/Message Cells/Content Views/MediaView.swift +++ b/Session/Conversations/Message Cells/Content Views/MediaView.swift @@ -60,6 +60,8 @@ public class MediaView: UIView { backgroundColor = Colors.unimportant clipsToBounds = true + layer.masksToBounds = true + layer.cornerRadius = VisibleMessageCell.largeCornerRadius createContents() } diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index 248ee419a..1e1c7e6de 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -19,12 +19,12 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel private lazy var authorLabelHeightConstraint = authorLabel.set(.height, to: 0) private lazy var profilePictureViewLeftConstraint = profilePictureView.pin(.left, to: .left, of: self, withInset: VisibleMessageCell.groupThreadHSpacing) private lazy var profilePictureViewWidthConstraint = profilePictureView.set(.width, to: Values.verySmallProfilePictureSize) - private lazy var bubbleViewLeftConstraint1 = bubbleView.pin(.left, to: .right, of: profilePictureView, withInset: VisibleMessageCell.groupThreadHSpacing) - private lazy var bubbleViewLeftConstraint2 = bubbleView.leftAnchor.constraint(greaterThanOrEqualTo: leftAnchor, constant: VisibleMessageCell.gutterSize) - private lazy var bubbleViewTopConstraint = bubbleView.pin(.top, to: .bottom, of: authorLabel, withInset: VisibleMessageCell.authorLabelBottomSpacing) - private lazy var bubbleViewRightConstraint1 = bubbleView.pin(.right, to: .right, of: self, withInset: -VisibleMessageCell.contactThreadHSpacing) - private lazy var bubbleViewRightConstraint2 = bubbleView.rightAnchor.constraint(lessThanOrEqualTo: rightAnchor, constant: -VisibleMessageCell.gutterSize) - private lazy var messageStatusImageViewTopConstraint = messageStatusImageView.pin(.top, to: .bottom, of: bubbleView, withInset: 0) + private lazy var bubbleViewLeftConstraint1 = snContentView.pin(.left, to: .right, of: profilePictureView, withInset: VisibleMessageCell.groupThreadHSpacing) + private lazy var bubbleViewLeftConstraint2 = snContentView.leftAnchor.constraint(greaterThanOrEqualTo: leftAnchor, constant: VisibleMessageCell.gutterSize) + private lazy var bubbleViewTopConstraint = snContentView.pin(.top, to: .bottom, of: authorLabel, withInset: VisibleMessageCell.authorLabelBottomSpacing) + private lazy var bubbleViewRightConstraint1 = snContentView.pin(.right, to: .right, of: self, withInset: -VisibleMessageCell.contactThreadHSpacing) + private lazy var bubbleViewRightConstraint2 = snContentView.rightAnchor.constraint(lessThanOrEqualTo: rightAnchor, constant: -VisibleMessageCell.gutterSize) + private lazy var messageStatusImageViewTopConstraint = messageStatusImageView.pin(.top, to: .bottom, of: snContentView, withInset: 0) private lazy var messageStatusImageViewWidthConstraint = messageStatusImageView.set(.width, to: VisibleMessageCell.messageStatusImageViewSize) private lazy var messageStatusImageViewHeightConstraint = messageStatusImageView.set(.height, to: VisibleMessageCell.messageStatusImageViewSize) private lazy var timerViewOutgoingMessageConstraint = timerView.pin(.left, to: .left, of: self, withInset: VisibleMessageCell.contactThreadHSpacing) @@ -79,7 +79,13 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel return result }() - private lazy var snContentView = UIView() + private lazy var snContentView: UIStackView = { + let result = UIStackView(arrangedSubviews: []) + result.axis = .vertical + result.spacing = Values.smallSpacing + result.alignment = .leading + return result + }() internal lazy var messageStatusImageView: UIImageView = { let result = UIImageView() @@ -170,29 +176,22 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel moderatorIconImageView.pin(.trailing, to: .trailing, of: profilePictureView, withInset: 1) moderatorIconImageView.pin(.bottom, to: .bottom, of: profilePictureView, withInset: 4.5) - // Bubble background view (used for the 'highlighted' animation) - addSubview(bubbleBackgroundView) - - // Bubble view - addSubview(bubbleView) + // Content view + addSubview(snContentView) bubbleViewLeftConstraint1.isActive = true bubbleViewTopConstraint.isActive = true bubbleViewRightConstraint1.isActive = true - bubbleBackgroundView.pin(to: bubbleView) +// bubbleBackgroundView.pin(to: snContentView) // Timer view addSubview(timerView) - timerView.center(.vertical, in: bubbleView) + timerView.center(.vertical, in: snContentView) timerViewOutgoingMessageConstraint.isActive = true - // Content view - bubbleView.addSubview(snContentView) - snContentView.pin(to: bubbleView) - // Message status image view addSubview(messageStatusImageView) messageStatusImageViewTopConstraint.isActive = true - messageStatusImageView.pin(.right, to: .right, of: bubbleView, withInset: -1) + messageStatusImageView.pin(.right, to: .right, of: snContentView, withInset: -1) messageStatusImageView.pin(.bottom, to: .bottom, of: self, withInset: -1) messageStatusImageViewWidthConstraint.isActive = true messageStatusImageViewHeightConstraint.isActive = true @@ -201,11 +200,11 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel addSubview(replyButton) replyButton.addSubview(replyIconImageView) replyIconImageView.center(in: replyButton) - replyButton.pin(.left, to: .right, of: bubbleView, withInset: Values.smallSpacing) - replyButton.center(.vertical, in: bubbleView) + replyButton.pin(.left, to: .right, of: snContentView, withInset: Values.smallSpacing) + replyButton.center(.vertical, in: snContentView) // Remaining constraints - authorLabel.pin(.left, to: .left, of: bubbleView, withInset: VisibleMessageCell.authorLabelInset) + authorLabel.pin(.left, to: .left, of: snContentView, withInset: VisibleMessageCell.authorLabelInset) } override func setUpGestureRecognizers() { @@ -374,12 +373,8 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel playbackInfo: ConversationViewModel.PlaybackInfo?, lastSearchText: String? ) { + let direction: Direction = cellViewModel.variant == .standardOutgoing ? .outgoing : .incoming let bodyLabelTextColor: UIColor = { - let direction: Direction = (cellViewModel.variant == .standardOutgoing ? - .outgoing : - .incoming - ) - switch (direction, AppModeManager.shared.currentAppMode) { case (.outgoing, .dark), (.incoming, .light): return .black case (.outgoing, .light): return Colors.grey @@ -387,14 +382,22 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel } }() - snContentView.subviews.forEach { $0.removeFromSuperview() } + snContentView.alignment = direction == .incoming ? .leading : .trailing + + for subview in snContentView.arrangedSubviews { + snContentView.removeArrangedSubview(subview) + subview.removeFromSuperview() + } + for subview in bubbleView.subviews { + subview.removeFromSuperview() + } albumView = nil bodyTextView = nil // Handle the deleted state first (it's much simpler than the others) guard cellViewModel.variant != .standardIncomingDeleted else { let deletedMessageView: DeletedMessageView = DeletedMessageView(textColor: bodyLabelTextColor) - snContentView.addSubview(deletedMessageView) + snContentView.addArrangedSubview(deletedMessageView) deletedMessageView.pin(to: snContentView) return } @@ -402,7 +405,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel // If it's an incoming media message and the thread isn't trusted then show the placeholder view if cellViewModel.cellType != .textOnlyMessage && cellViewModel.variant == .standardIncoming && !cellViewModel.threadIsTrusted { let mediaPlaceholderView = MediaPlaceholderView(cellViewModel: cellViewModel, textColor: bodyLabelTextColor) - snContentView.addSubview(mediaPlaceholderView) + snContentView.addArrangedSubview(mediaPlaceholderView) mediaPlaceholderView.pin(to: snContentView) return } @@ -429,8 +432,9 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel bodyLabelTextColor: bodyLabelTextColor, lastSearchText: lastSearchText ) - snContentView.addSubview(linkPreviewView) - linkPreviewView.pin(to: snContentView) + bubbleView.addSubview(linkPreviewView) + bubbleView.pin(to: linkPreviewView, withInset: -inset) + snContentView.addArrangedSubview(bubbleView) self.bodyTextView = linkPreviewView.bodyTextView case .openGroupInvitation: @@ -440,9 +444,9 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel textColor: bodyLabelTextColor, isOutgoing: (cellViewModel.variant == .standardOutgoing) ) - - snContentView.addSubview(openGroupInvitationView) - openGroupInvitationView.pin(to: snContentView) + bubbleView.addSubview(openGroupInvitationView) + bubbleView.pin(to: openGroupInvitationView, withInset: -inset) + snContentView.addArrangedSubview(openGroupInvitationView) } } else { @@ -483,15 +487,29 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel stackView.addArrangedSubview(bodyTextView) // Constraints - snContentView.addSubview(stackView) - stackView.pin(to: snContentView, withInset: inset) + bubbleView.addSubview(stackView) + stackView.pin(to: bubbleView, withInset: inset) + snContentView.addArrangedSubview(bubbleView) } case .mediaMessage: - // Stack view - let stackView = UIStackView(arrangedSubviews: []) - stackView.axis = .vertical - stackView.spacing = Values.smallSpacing + // Body text view + if let body: String = cellViewModel.body, !body.isEmpty { + let inset: CGFloat = 12 + let maxWidth: CGFloat = (VisibleMessageCell.getMaxWidth(for: cellViewModel) - 2 * inset) + let bodyTextView = VisibleMessageCell.getBodyTextView( + for: cellViewModel, + with: maxWidth, + textColor: bodyLabelTextColor, + searchText: lastSearchText, + delegate: self + ) + + self.bodyTextView = bodyTextView + bubbleView.addSubview(bodyTextView) + bodyTextView.pin(to: bubbleView, withInset: inset) + snContentView.addArrangedSubview(bubbleView) + } // Album view let maxMessageWidth: CGFloat = VisibleMessageCell.getMaxWidth(for: cellViewModel) @@ -508,34 +526,16 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel albumView.set(.width, to: size.width) albumView.set(.height, to: size.height) albumView.loadMedia() - stackView.addArrangedSubview(albumView) - - // Body text view - if let body: String = cellViewModel.body, !body.isEmpty { - let inset: CGFloat = 12 - let maxWidth: CGFloat = (size.width - (2 * inset)) - let bodyTextView = VisibleMessageCell.getBodyTextView( - for: cellViewModel, - with: maxWidth, - textColor: bodyLabelTextColor, - searchText: lastSearchText, - delegate: self - ) - - self.bodyTextView = bodyTextView - stackView.addArrangedSubview(UIView(wrapping: bodyTextView, withInsets: UIEdgeInsets(top: 0, left: inset, bottom: inset, right: inset))) - } + snContentView.addArrangedSubview(albumView) + unloadContent = { albumView.unloadMedia() } - // Constraints - snContentView.addSubview(stackView) - stackView.pin(to: snContentView) - case .audio: guard let attachment: Attachment = cellViewModel.attachments?.first(where: { $0.isAudio }) else { return } + let inset: CGFloat = 12 let voiceMessageView: VoiceMessageView = VoiceMessageView() voiceMessageView.update( with: attachment, @@ -544,9 +544,10 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel playbackRate: (playbackInfo?.playbackRate ?? 1), oldPlaybackRate: (playbackInfo?.oldPlaybackRate ?? 1) ) - - snContentView.addSubview(voiceMessageView) - voiceMessageView.pin(to: snContentView) + + bubbleView.addSubview(voiceMessageView) + voiceMessageView.pin(to: bubbleView, withInset: inset) + snContentView.addArrangedSubview(bubbleView) self.voiceMessageView = voiceMessageView case .genericAttachment: @@ -555,15 +556,6 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel let inset: CGFloat = 12 let maxWidth = (VisibleMessageCell.getMaxWidth(for: cellViewModel) - 2 * inset) - // Stack view - let stackView = UIStackView(arrangedSubviews: []) - stackView.axis = .vertical - stackView.spacing = Values.smallSpacing - - // Document view - let documentView = DocumentView(attachment: attachment, textColor: bodyLabelTextColor) - stackView.addArrangedSubview(documentView) - // Body text view if let body: String = cellViewModel.body, !body.isEmpty { // delegate should always be set at this point let bodyTextView = VisibleMessageCell.getBodyTextView( @@ -575,12 +567,14 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel ) self.bodyTextView = bodyTextView - stackView.addArrangedSubview(bodyTextView) + bubbleView.addSubview(bodyTextView) + bodyTextView.pin(to: bubbleView, withInset: inset) + snContentView.addArrangedSubview(bubbleView) } - // Constraints - snContentView.addSubview(stackView) - stackView.pin(to: snContentView, withInset: inset) + // Document view + let documentView = DocumentView(attachment: attachment, textColor: bodyLabelTextColor) + snContentView.addArrangedSubview(documentView) } } @@ -720,7 +714,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel UIImpactFeedbackGenerator(style: .heavy).impactOccurred() reply() } - else if bubbleView.frame.contains(location) { + else if snContentView.frame.contains(location) { delegate?.handleItemTapped(cellViewModel, gestureRecognizer: gestureRecognizer) } } From a123b36a470752b36eed3bd77b1b93d8c4451587 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Fri, 15 Jul 2022 10:50:27 +1000 Subject: [PATCH 02/12] minor fixes for voice messages and link preview --- .../Conversations/Message Cells/VisibleMessageCell.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index 1e1c7e6de..cb087c0bf 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -433,7 +433,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel lastSearchText: lastSearchText ) bubbleView.addSubview(linkPreviewView) - bubbleView.pin(to: linkPreviewView, withInset: -inset) + linkPreviewView.pin(to: bubbleView, withInset: 0) snContentView.addArrangedSubview(bubbleView) self.bodyTextView = linkPreviewView.bodyTextView @@ -445,7 +445,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel isOutgoing: (cellViewModel.variant == .standardOutgoing) ) bubbleView.addSubview(openGroupInvitationView) - bubbleView.pin(to: openGroupInvitationView, withInset: -inset) + bubbleView.pin(to: openGroupInvitationView) snContentView.addArrangedSubview(openGroupInvitationView) } } @@ -535,7 +535,6 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel return } - let inset: CGFloat = 12 let voiceMessageView: VoiceMessageView = VoiceMessageView() voiceMessageView.update( with: attachment, @@ -546,7 +545,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel ) bubbleView.addSubview(voiceMessageView) - voiceMessageView.pin(to: bubbleView, withInset: inset) + voiceMessageView.pin(to: bubbleView) snContentView.addArrangedSubview(bubbleView) self.voiceMessageView = voiceMessageView From e2d9ba6882fe62dc39e11515ba3284bcd6cc53f5 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Fri, 15 Jul 2022 11:26:15 +1000 Subject: [PATCH 03/12] fix pan gesture of message cell --- .../Message Cells/VisibleMessageCell.swift | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index cb087c0bf..de5471caf 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -39,9 +39,9 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel // MARK: - UI Components private lazy var viewsToMoveForReply: [UIView] = [ - bubbleView, - bubbleBackgroundView, + snContentView, profilePictureView, + moderatorIconImageView, replyButton, timerView, messageStatusImageView @@ -792,19 +792,22 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel // MARK: - Convenience private func getCornersToRound() -> UIRectCorner { - guard viewModel?.isOnlyMessageInCluster == false else { return .allCorners } - - let direction: Direction = (viewModel?.variant == .standardOutgoing ? .outgoing : .incoming) - - switch (viewModel?.positionInCluster, direction) { - case (.top, .outgoing): return [ .bottomLeft, .topLeft, .topRight ] - case (.middle, .outgoing): return [ .bottomLeft, .topLeft ] - case (.bottom, .outgoing): return [ .bottomRight, .bottomLeft, .topLeft ] - case (.top, .incoming): return [ .topLeft, .topRight, .bottomRight ] - case (.middle, .incoming): return [ .topRight, .bottomRight ] - case (.bottom, .incoming): return [ .topRight, .bottomRight, .bottomLeft ] - case (.none, _): return .allCorners - } + return .allCorners + + // FIXME: Leave the code here just in case we want this again. +// guard viewModel?.isOnlyMessageInCluster == false else { return .allCorners } +// +// let direction: Direction = (viewModel?.variant == .standardOutgoing ? .outgoing : .incoming) +// +// switch (viewModel?.positionInCluster, direction) { +// case (.top, .outgoing): return [ .bottomLeft, .topLeft, .topRight ] +// case (.middle, .outgoing): return [ .bottomLeft, .topLeft ] +// case (.bottom, .outgoing): return [ .bottomRight, .bottomLeft, .topLeft ] +// case (.top, .incoming): return [ .topLeft, .topRight, .bottomRight ] +// case (.middle, .incoming): return [ .topRight, .bottomRight ] +// case (.bottom, .incoming): return [ .topRight, .bottomRight, .bottomLeft ] +// case (.none, _): return .allCorners +// } } private func getCornerMask(from rectCorner: UIRectCorner) -> CACornerMask { From 9ec703b69887d7d2e99070272604e21157afbc7e Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Tue, 19 Jul 2022 14:32:44 +1000 Subject: [PATCH 04/12] adjust album view --- .../Content Views/MediaAlbumView.swift | 82 ++----------------- .../Message Cells/VisibleMessageCell.swift | 2 +- 2 files changed, 8 insertions(+), 76 deletions(-) diff --git a/Session/Conversations/Message Cells/Content Views/MediaAlbumView.swift b/Session/Conversations/Message Cells/Content Views/MediaAlbumView.swift index 5600fa62b..2ed625fda 100644 --- a/Session/Conversations/Message Cells/Content Views/MediaAlbumView.swift +++ b/Session/Conversations/Message Cells/Content Views/MediaAlbumView.swift @@ -8,8 +8,8 @@ public class MediaAlbumView: UIStackView { public let itemViews: [MediaView] public var moreItemsView: MediaView? - private static let kSpacingPts: CGFloat = 2 - private static let kMaxItems = 5 + private static let kSpacingPts: CGFloat = 4 + private static let kMaxItems = 3 @available(*, unavailable, message: "use other init() instead.") required public init(coder aDecoder: NSCoder) { @@ -65,8 +65,8 @@ public class MediaAlbumView: UIStackView { self.axis = .horizontal self.distribution = .fillEqually self.spacing = MediaAlbumView.kSpacingPts - - case 3: + + default: // x // X x // Big on left, 2 small on right. @@ -90,64 +90,9 @@ public class MediaAlbumView: UIStackView { ) self.axis = .horizontal self.spacing = MediaAlbumView.kSpacingPts - - case 4: - // X X - // X X - // Square - let imageSize = (maxMessageWidth - MediaAlbumView.kSpacingPts) / 2 - - let topViews = Array(itemViews[0..<2]) - addArrangedSubview( - newRow( - rowViews: topViews, - axis: .horizontal, - viewSize: imageSize - ) - ) - - let bottomViews = Array(itemViews[2..<4]) - addArrangedSubview( - newRow( - rowViews: bottomViews, - axis: .horizontal, - viewSize: imageSize - ) - ) - - self.axis = .vertical - self.spacing = MediaAlbumView.kSpacingPts - - default: - // X X - // xxx - // 2 big on top, 3 small on bottom. - let bigImageSize = (maxMessageWidth - MediaAlbumView.kSpacingPts) / 2 - let smallImageSize = (maxMessageWidth - MediaAlbumView.kSpacingPts * 2) / 3 - - let topViews = Array(itemViews[0..<2]) - addArrangedSubview( - newRow( - rowViews: topViews, - axis: .horizontal, - viewSize: bigImageSize - ) - ) - - let bottomViews = Array(itemViews[2..<5]) - addArrangedSubview( - newRow( - rowViews: bottomViews, - axis: .horizontal, - viewSize: smallImageSize - ) - ) - - self.axis = .vertical - self.spacing = MediaAlbumView.kSpacingPts if items.count > MediaAlbumView.kMaxItems { - guard let lastView = bottomViews.last else { + guard let lastView = rightViews.last else { owsFailDebug("Missing lastView") return } @@ -263,13 +208,8 @@ public class MediaAlbumView: UIStackView { let itemCount = itemsToDisplay(forItems: items).count switch itemCount { - case 0, 1, 4: + case 0, 1: // X - // - // or - // - // XX - // XX // Square return CGSize(width: maxMessageWidth, height: maxMessageWidth) @@ -279,21 +219,13 @@ public class MediaAlbumView: UIStackView { let imageSize = (maxMessageWidth - kSpacingPts) / 2 return CGSize(width: maxMessageWidth, height: imageSize) - case 3: + default: // x // X x // Big on left, 2 small on right. let smallImageSize = (maxMessageWidth - kSpacingPts * 2) / 3 let bigImageSize = smallImageSize * 2 + kSpacingPts return CGSize(width: maxMessageWidth, height: bigImageSize) - - default: - // X X - // xxx - // 2 big on top, 3 small on bottom. - let bigImageSize = (maxMessageWidth - kSpacingPts) / 2 - let smallImageSize = (maxMessageWidth - kSpacingPts * 2) / 3 - return CGSize(width: maxMessageWidth, height: bigImageSize + smallImageSize + kSpacingPts) } } diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index de5471caf..f57d91806 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -82,7 +82,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel private lazy var snContentView: UIStackView = { let result = UIStackView(arrangedSubviews: []) result.axis = .vertical - result.spacing = Values.smallSpacing + result.spacing = Values.verySmallSpacing result.alignment = .leading return result }() From cd9a8330db97b64ff017133dd519802bd7d61fa1 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Tue, 19 Jul 2022 15:53:10 +1000 Subject: [PATCH 05/12] fix cell ui for documents --- .../Message Cells/VisibleMessageCell.swift | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index a2547bb9e..43191b9cc 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -556,7 +556,16 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel let inset: CGFloat = 12 let maxWidth = (VisibleMessageCell.getMaxWidth(for: cellViewModel) - 2 * inset) + + // Stack view + let stackView = UIStackView(arrangedSubviews: []) + stackView.axis = .vertical + stackView.spacing = Values.smallSpacing + // Document view + let documentView = DocumentView(attachment: attachment, textColor: bodyLabelTextColor) + stackView.addArrangedSubview(documentView) + // Body text view if let body: String = cellViewModel.body, !body.isEmpty { // delegate should always be set at this point let bodyTextView = VisibleMessageCell.getBodyTextView( @@ -568,14 +577,12 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel ) self.bodyTextView = bodyTextView - bubbleView.addSubview(bodyTextView) - bodyTextView.pin(to: bubbleView, withInset: inset) - snContentView.addArrangedSubview(bubbleView) + stackView.addArrangedSubview(bodyTextView) } - // Document view - let documentView = DocumentView(attachment: attachment, textColor: bodyLabelTextColor) - snContentView.addArrangedSubview(documentView) + bubbleView.addSubview(stackView) + stackView.pin(to: bubbleView, withInset: inset) + snContentView.addArrangedSubview(bubbleView) } } From 44c962eea7aa077bc3cb6d4c26b2a70b8110e1b6 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Wed, 20 Jul 2022 10:41:33 +1000 Subject: [PATCH 06/12] fix ui issue #644 for open group messages --- Session/Conversations/Message Cells/VisibleMessageCell.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index 43191b9cc..11913b08e 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -144,6 +144,8 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel return result }() + static var leftGutterSize: CGFloat { groupThreadHSpacing + profilePictureSize + groupThreadHSpacing } + // MARK: Direction & Position enum Direction { case incoming, outgoing } @@ -931,7 +933,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel cellViewModel.threadVariant == .openGroup || cellViewModel.threadVariant == .closedGroup ) - let leftGutterSize = (isGroupThread ? gutterSize : contactThreadHSpacing) + let leftGutterSize = (isGroupThread ? leftGutterSize : contactThreadHSpacing) return (screen.width - leftGutterSize - gutterSize) From 82429a856629f629656cf030e8e0a6bbbf7ec3a0 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Wed, 20 Jul 2022 10:46:41 +1000 Subject: [PATCH 07/12] fix bubble background for deleted messages and media message placeholder --- .../Message Cells/VisibleMessageCell.swift | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index 11913b08e..493ce636a 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -399,16 +399,18 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel // Handle the deleted state first (it's much simpler than the others) guard cellViewModel.variant != .standardIncomingDeleted else { let deletedMessageView: DeletedMessageView = DeletedMessageView(textColor: bodyLabelTextColor) - snContentView.addArrangedSubview(deletedMessageView) - deletedMessageView.pin(to: snContentView) + bubbleView.addSubview(deletedMessageView) + deletedMessageView.pin(to: bubbleView) + snContentView.addArrangedSubview(bubbleView) return } // If it's an incoming media message and the thread isn't trusted then show the placeholder view if cellViewModel.cellType != .textOnlyMessage && cellViewModel.variant == .standardIncoming && !cellViewModel.threadIsTrusted { let mediaPlaceholderView = MediaPlaceholderView(cellViewModel: cellViewModel, textColor: bodyLabelTextColor) - snContentView.addArrangedSubview(mediaPlaceholderView) - mediaPlaceholderView.pin(to: snContentView) + bubbleView.addSubview(mediaPlaceholderView) + mediaPlaceholderView.pin(to: bubbleView) + snContentView.addArrangedSubview(bubbleView) return } From e1c5d9411d2834d8f46000eb003d32a2e56b20e6 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Wed, 20 Jul 2022 11:47:54 +1000 Subject: [PATCH 08/12] fix highlighting --- .../Message Cells/VisibleMessageCell.swift | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index 493ce636a..a7929b69d 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -19,11 +19,11 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel private lazy var authorLabelHeightConstraint = authorLabel.set(.height, to: 0) private lazy var profilePictureViewLeftConstraint = profilePictureView.pin(.left, to: .left, of: self, withInset: VisibleMessageCell.groupThreadHSpacing) private lazy var profilePictureViewWidthConstraint = profilePictureView.set(.width, to: Values.verySmallProfilePictureSize) - private lazy var bubbleViewLeftConstraint1 = snContentView.pin(.left, to: .right, of: profilePictureView, withInset: VisibleMessageCell.groupThreadHSpacing) - private lazy var bubbleViewLeftConstraint2 = snContentView.leftAnchor.constraint(greaterThanOrEqualTo: leftAnchor, constant: VisibleMessageCell.gutterSize) - private lazy var bubbleViewTopConstraint = snContentView.pin(.top, to: .bottom, of: authorLabel, withInset: VisibleMessageCell.authorLabelBottomSpacing) - private lazy var bubbleViewRightConstraint1 = snContentView.pin(.right, to: .right, of: self, withInset: -VisibleMessageCell.contactThreadHSpacing) - private lazy var bubbleViewRightConstraint2 = snContentView.rightAnchor.constraint(lessThanOrEqualTo: rightAnchor, constant: -VisibleMessageCell.gutterSize) + private lazy var contentViewLeftConstraint1 = snContentView.pin(.left, to: .right, of: profilePictureView, withInset: VisibleMessageCell.groupThreadHSpacing) + private lazy var contentViewLeftConstraint2 = snContentView.leftAnchor.constraint(greaterThanOrEqualTo: leftAnchor, constant: VisibleMessageCell.gutterSize) + private lazy var contentViewTopConstraint = snContentView.pin(.top, to: .bottom, of: authorLabel, withInset: VisibleMessageCell.authorLabelBottomSpacing) + private lazy var contentViewRightConstraint1 = snContentView.pin(.right, to: .right, of: self, withInset: -VisibleMessageCell.contactThreadHSpacing) + private lazy var contentViewRightConstraint2 = snContentView.rightAnchor.constraint(lessThanOrEqualTo: rightAnchor, constant: -VisibleMessageCell.gutterSize) private lazy var messageStatusImageViewTopConstraint = messageStatusImageView.pin(.top, to: .bottom, of: snContentView, withInset: 0) private lazy var messageStatusImageViewWidthConstraint = messageStatusImageView.set(.width, to: VisibleMessageCell.messageStatusImageViewSize) private lazy var messageStatusImageViewHeightConstraint = messageStatusImageView.set(.height, to: VisibleMessageCell.messageStatusImageViewSize) @@ -180,10 +180,13 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel // Content view addSubview(snContentView) - bubbleViewLeftConstraint1.isActive = true - bubbleViewTopConstraint.isActive = true - bubbleViewRightConstraint1.isActive = true -// bubbleBackgroundView.pin(to: snContentView) + contentViewLeftConstraint1.isActive = true + contentViewTopConstraint.isActive = true + contentViewRightConstraint1.isActive = true + + // Bubble background view + bubbleBackgroundView.addSubview(bubbleView) + bubbleBackgroundView.pin(to: bubbleView) // Timer view addSubview(timerView) @@ -254,15 +257,15 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel moderatorIconImageView.isHidden = (!cellViewModel.isSenderOpenGroupModerator || !cellViewModel.shouldShowProfile) // Bubble view - bubbleViewLeftConstraint1.isActive = ( + contentViewLeftConstraint1.isActive = ( cellViewModel.variant == .standardIncoming || cellViewModel.variant == .standardIncomingDeleted ) - bubbleViewLeftConstraint1.constant = (isGroupThread ? VisibleMessageCell.groupThreadHSpacing : VisibleMessageCell.contactThreadHSpacing) - bubbleViewLeftConstraint2.isActive = (cellViewModel.variant == .standardOutgoing) - bubbleViewTopConstraint.constant = (cellViewModel.senderName == nil ? 0 : VisibleMessageCell.authorLabelBottomSpacing) - bubbleViewRightConstraint1.isActive = (cellViewModel.variant == .standardOutgoing) - bubbleViewRightConstraint2.isActive = ( + contentViewLeftConstraint1.constant = (isGroupThread ? VisibleMessageCell.groupThreadHSpacing : VisibleMessageCell.contactThreadHSpacing) + contentViewLeftConstraint2.isActive = (cellViewModel.variant == .standardOutgoing) + contentViewTopConstraint.constant = (cellViewModel.senderName == nil ? 0 : VisibleMessageCell.authorLabelBottomSpacing) + contentViewRightConstraint1.isActive = (cellViewModel.variant == .standardOutgoing) + contentViewRightConstraint2.isActive = ( cellViewModel.variant == .standardIncoming || cellViewModel.variant == .standardIncomingDeleted ) @@ -401,7 +404,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel let deletedMessageView: DeletedMessageView = DeletedMessageView(textColor: bodyLabelTextColor) bubbleView.addSubview(deletedMessageView) deletedMessageView.pin(to: bubbleView) - snContentView.addArrangedSubview(bubbleView) + snContentView.addArrangedSubview(bubbleBackgroundView) return } @@ -410,7 +413,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel let mediaPlaceholderView = MediaPlaceholderView(cellViewModel: cellViewModel, textColor: bodyLabelTextColor) bubbleView.addSubview(mediaPlaceholderView) mediaPlaceholderView.pin(to: bubbleView) - snContentView.addArrangedSubview(bubbleView) + snContentView.addArrangedSubview(bubbleBackgroundView) return } @@ -438,7 +441,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel ) bubbleView.addSubview(linkPreviewView) linkPreviewView.pin(to: bubbleView, withInset: 0) - snContentView.addArrangedSubview(bubbleView) + snContentView.addArrangedSubview(bubbleBackgroundView) self.bodyTextView = linkPreviewView.bodyTextView case .openGroupInvitation: @@ -450,7 +453,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel ) bubbleView.addSubview(openGroupInvitationView) bubbleView.pin(to: openGroupInvitationView) - snContentView.addArrangedSubview(openGroupInvitationView) + snContentView.addArrangedSubview(bubbleBackgroundView) } } else { @@ -495,7 +498,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel // Constraints bubbleView.addSubview(stackView) stackView.pin(to: bubbleView, withInset: inset) - snContentView.addArrangedSubview(bubbleView) + snContentView.addArrangedSubview(bubbleBackgroundView) } case .mediaMessage: @@ -514,7 +517,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel self.bodyTextView = bodyTextView bubbleView.addSubview(bodyTextView) bodyTextView.pin(to: bubbleView, withInset: inset) - snContentView.addArrangedSubview(bubbleView) + snContentView.addArrangedSubview(bubbleBackgroundView) } // Album view @@ -552,7 +555,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel bubbleView.addSubview(voiceMessageView) voiceMessageView.pin(to: bubbleView) - snContentView.addArrangedSubview(bubbleView) + snContentView.addArrangedSubview(bubbleBackgroundView) self.voiceMessageView = voiceMessageView case .genericAttachment: @@ -586,7 +589,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel bubbleView.addSubview(stackView) stackView.pin(to: bubbleView, withInset: inset) - snContentView.addArrangedSubview(bubbleView) + snContentView.addArrangedSubview(bubbleBackgroundView) } } From 290ccdc639753af1d5972c9b3a3c269400ea99ce Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Wed, 20 Jul 2022 14:08:46 +1000 Subject: [PATCH 09/12] fix long press snapshot of messages --- Session/Conversations/ConversationVC+Interaction.swift | 2 +- Session/Conversations/Message Cells/VisibleMessageCell.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index 33dfce0fb..5d8b3cb95 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -649,7 +649,7 @@ extension ConversationVC: .elements .firstIndex(of: cellViewModel), let cell = tableView.cellForRow(at: IndexPath(row: index, section: sectionIndex)) as? VisibleMessageCell, - let snapshot = cell.bubbleView.snapshotView(afterScreenUpdates: false), + let snapshot = cell.snContentView.snapshotView(afterScreenUpdates: false), contextMenuWindow == nil, let actions: [ContextMenuVC.Action] = ContextMenuVC.actions( for: cellViewModel, diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index a7929b69d..d982e1eb6 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -79,7 +79,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel return result }() - private lazy var snContentView: UIStackView = { + lazy var snContentView: UIStackView = { let result = UIStackView(arrangedSubviews: []) result.axis = .vertical result.spacing = Values.verySmallSpacing From 85b3015d719a23fb29012c7233777707a7aef4de Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Wed, 10 Aug 2022 13:51:48 +1000 Subject: [PATCH 10/12] clean --- Podfile.lock | 2 +- .../Message Cells/VisibleMessageCell.swift | 21 +------------------ 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index 5e750d933..37f4ac9c5 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -244,4 +244,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: f0857369c4831b2e5c1946345e76e493f3286805 -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index d982e1eb6..1227de446 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -599,7 +599,7 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel } private func updateBubbleViewCorners() { - let cornersToRound: UIRectCorner = getCornersToRound() + let cornersToRound: UIRectCorner = .allCorners bubbleBackgroundView.layer.cornerRadius = VisibleMessageCell.largeCornerRadius bubbleBackgroundView.layer.maskedCorners = getCornerMask(from: cornersToRound) @@ -807,25 +807,6 @@ final class VisibleMessageCell: MessageCell, UITextViewDelegate, BodyTextViewDel // MARK: - Convenience - private func getCornersToRound() -> UIRectCorner { - return .allCorners - - // FIXME: Leave the code here just in case we want this again. -// guard viewModel?.isOnlyMessageInCluster == false else { return .allCorners } -// -// let direction: Direction = (viewModel?.variant == .standardOutgoing ? .outgoing : .incoming) -// -// switch (viewModel?.positionInCluster, direction) { -// case (.top, .outgoing): return [ .bottomLeft, .topLeft, .topRight ] -// case (.middle, .outgoing): return [ .bottomLeft, .topLeft ] -// case (.bottom, .outgoing): return [ .bottomRight, .bottomLeft, .topLeft ] -// case (.top, .incoming): return [ .topLeft, .topRight, .bottomRight ] -// case (.middle, .incoming): return [ .topRight, .bottomRight ] -// case (.bottom, .incoming): return [ .topRight, .bottomRight, .bottomLeft ] -// case (.none, _): return .allCorners -// } - } - private func getCornerMask(from rectCorner: UIRectCorner) -> CACornerMask { guard !rectCorner.contains(.allCorners) else { return [ .layerMaxXMinYCorner, .layerMinXMinYCorner, .layerMaxXMaxYCorner, .layerMinXMaxYCorner] From 827ecee7b01cff631943f8d25d106cf6f709438a Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Wed, 10 Aug 2022 14:08:17 +1000 Subject: [PATCH 11/12] tweak: fix the layout of snapshot in context menu view --- Session/Conversations/ConversationVC+Interaction.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index 23a164595..54d820bb4 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -668,7 +668,7 @@ extension ConversationVC: self.contextMenuWindow = ContextMenuWindow() self.contextMenuVC = ContextMenuVC( snapshot: snapshot, - frame: cell.convert(cell.bubbleView.frame, to: keyWindow), + frame: cell.convert(cell.snContentView.frame, to: keyWindow), cellViewModel: cellViewModel, actions: actions ) { [weak self] in From 76833c0b9fb50e55d1d215d11e4933faddea567e Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Wed, 10 Aug 2022 14:19:18 +1000 Subject: [PATCH 12/12] tweak: fix album view background in visible message cells --- .../Message Cells/Content Views/MediaAlbumView.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/Session/Conversations/Message Cells/Content Views/MediaAlbumView.swift b/Session/Conversations/Message Cells/Content Views/MediaAlbumView.swift index 2ed625fda..44d46b571 100644 --- a/Session/Conversations/Message Cells/Content Views/MediaAlbumView.swift +++ b/Session/Conversations/Message Cells/Content Views/MediaAlbumView.swift @@ -35,9 +35,6 @@ public class MediaAlbumView: UIStackView { super.init(frame: .zero) - // UIStackView's backgroundColor property has no effect. - addBackgroundView(withBackgroundColor: Colors.navigationBarBackground) - createContents(maxMessageWidth: maxMessageWidth) }