pull/347/head
nielsandriesse 4 years ago
parent 78456efe62
commit a9fb52acf8

@ -3,12 +3,13 @@
// Tapping replies
// Mentions
// Remaining send logic
// Paging
// Paging glitch
// Blocking
// Subtitle
// Resending failed messages
// Linkification
// Link previews
// Canceling replies
final class ConversationVC : BaseVC, ConversationViewModelDelegate, UITableViewDataSource, UITableViewDelegate {
let thread: TSThread

@ -14,7 +14,7 @@ public final class InputTextView : UITextView, UITextViewDelegate {
// MARK: Settings
private let minHeight: CGFloat = 22
private let maxHeight: CGFloat = 120
private let maxHeight: CGFloat = 80
// MARK: Lifecycle
init(delegate: InputTextViewDelegate) {

@ -21,7 +21,7 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate {
private lazy var quoteDraftContainer: UIView = {
let result = UIView()
result.heightAnchor.constraint(greaterThanOrEqualToConstant: 12).isActive = true
result.heightAnchor.constraint(greaterThanOrEqualToConstant: 4).isActive = true
return result
}()
@ -74,6 +74,7 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate {
let bottomStackView = UIStackView(arrangedSubviews: [ inputTextView, container(for: sendButton) ])
bottomStackView.axis = .horizontal
bottomStackView.spacing = Values.smallSpacing
bottomStackView.alignment = .center
// Main stack view
let mainStackView = UIStackView(arrangedSubviews: [ buttonStackView, quoteDraftContainer, bottomStackView ])
mainStackView.axis = .vertical
@ -83,7 +84,7 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate {
addSubview(mainStackView)
mainStackView.pin(.top, to: .bottom, of: separator)
mainStackView.pin([ UIView.HorizontalEdge.leading, UIView.HorizontalEdge.trailing ], to: self)
mainStackView.pin(.bottom, to: .bottom, of: self, withInset: -12)
mainStackView.pin(.bottom, to: .bottom, of: self, withInset: -2)
}
// MARK: Updating
@ -96,13 +97,13 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate {
guard let quoteDraftInfo = quoteDraftInfo else { return }
let direction: QuoteView.Direction = quoteDraftInfo.isOutgoing ? .outgoing : .incoming
let hInset: CGFloat = 6
let maxMessageWidth = quoteDraftContainer.bounds.width - 2 * hInset
let quoteView = QuoteView(for: quoteDraftInfo.model, direction: direction, hInset: hInset, maxMessageWidth: maxMessageWidth)
let maxWidth = quoteDraftContainer.bounds.width
let quoteView = QuoteView(for: quoteDraftInfo.model, direction: direction, hInset: hInset, maxWidth: maxWidth)
quoteDraftContainer.addSubview(quoteView)
quoteView.pin(.left, to: .left, of: quoteDraftContainer, withInset: hInset)
quoteView.pin(.top, to: .top, of: quoteDraftContainer, withInset: 12)
quoteView.pin(.right, to: .right, of: quoteDraftContainer, withInset: -hInset)
quoteView.pin(.bottom, to: .bottom, of: quoteDraftContainer, withInset: -12)
quoteView.pin(.bottom, to: .bottom, of: quoteDraftContainer, withInset: -6)
}
// MARK: Interaction

@ -3,7 +3,14 @@ final class QuoteView : UIView {
private let mode: Mode
private let direction: Direction
private let hInset: CGFloat
private let maxMessageWidth: CGFloat
private let maxWidth: CGFloat
private var maxBodyLabelHeight: CGFloat {
switch mode {
case .regular: return 60
case .draft: return 40
}
}
private var attachments: [OWSAttachmentInfo] {
switch mode {
@ -54,7 +61,8 @@ final class QuoteView : UIView {
private var lineColor: UIColor {
switch (mode, AppModeManager.shared.currentAppMode) {
case (.regular, _), (.draft, .light): return .black
case (.regular, .light), (.draft, .light): return .black
case (.regular, .dark): return (direction == .outgoing) ? .black : Colors.accent
case (.draft, .dark): return Colors.accent
}
}
@ -80,20 +88,21 @@ final class QuoteView : UIView {
static let thumbnailSize: CGFloat = 48
static let iconSize: CGFloat = 24
static let labelStackViewSpacing: CGFloat = 2
static let labelStackViewVMargin: CGFloat = 4
// MARK: Lifecycle
init(for viewItem: ConversationViewItem, direction: Direction, hInset: CGFloat, maxMessageWidth: CGFloat) {
init(for viewItem: ConversationViewItem, direction: Direction, hInset: CGFloat, maxWidth: CGFloat) {
self.mode = .regular(viewItem)
self.maxMessageWidth = maxMessageWidth
self.maxWidth = maxWidth
self.direction = direction
self.hInset = hInset
super.init(frame: CGRect.zero)
setUpViewHierarchy()
}
init(for model: OWSQuotedReplyModel, direction: Direction, hInset: CGFloat, maxMessageWidth: CGFloat) {
init(for model: OWSQuotedReplyModel, direction: Direction, hInset: CGFloat, maxWidth: CGFloat) {
self.mode = .draft(model)
self.maxMessageWidth = maxMessageWidth
self.maxWidth = maxWidth
self.direction = direction
self.hInset = hInset
super.init(frame: CGRect.zero)
@ -113,12 +122,15 @@ final class QuoteView : UIView {
let thumbnailSize = QuoteView.thumbnailSize
let iconSize = QuoteView.iconSize
let labelStackViewSpacing = QuoteView.labelStackViewSpacing
let labelStackViewVMargin = QuoteView.labelStackViewVMargin
let smallSpacing = Values.smallSpacing
let availableWidth: CGFloat
// Subtract smallSpacing twice; once for the spacing in between the stack view elements and
// once for the trailing margin.
if !hasAttachments {
availableWidth = maxMessageWidth - 2 * hInset - Values.accentLineThickness - 2 * smallSpacing
availableWidth = maxWidth - 2 * hInset - Values.accentLineThickness - 2 * smallSpacing
} else {
availableWidth = maxMessageWidth - 2 * hInset - thumbnailSize - 2 * smallSpacing
availableWidth = maxWidth - 2 * hInset - thumbnailSize - 2 * smallSpacing
}
let availableSpace = CGSize(width: availableWidth, height: .greatestFiniteMagnitude)
var body = self.body
@ -159,10 +171,10 @@ final class QuoteView : UIView {
bodyLabel.numberOfLines = 0
bodyLabel.lineBreakMode = .byTruncatingTail
let isOutgoing = (direction == .outgoing)
bodyLabel.font = .systemFont(ofSize: Values.smallFontSize)
bodyLabel.attributedText = given(body) { MentionUtilities.highlightMentions(in: $0, isOutgoingMessage: isOutgoing, threadID: threadID, attributes: [:]) }
?? given(attachments.first?.contentType) { NSAttributedString(string: MIMETypeUtil.isAudio($0) ? "Audio" : "Document") } ?? NSAttributedString(string: "Document")
bodyLabel.textColor = textColor
bodyLabel.font = .systemFont(ofSize: Values.smallFontSize)
if hasAttachments {
bodyLabel.numberOfLines = 1
}
@ -179,6 +191,8 @@ final class QuoteView : UIView {
labelStackView.axis = .vertical
labelStackView.spacing = labelStackViewSpacing
labelStackView.set(.width, to: max(bodyLabelSize.width, authorLabelSize.width))
labelStackView.isLayoutMarginsRelativeArrangement = true
labelStackView.layoutMargins = UIEdgeInsets(top: labelStackViewVMargin, left: 0, bottom: labelStackViewVMargin, right: 0)
mainStackView.addArrangedSubview(labelStackView)
} else {
mainStackView.addArrangedSubview(bodyLabel)
@ -189,17 +203,19 @@ final class QuoteView : UIView {
if !isGroupThread {
bodyLabel.set(.width, to: bodyLabelSize.width)
}
let maxBodyLabelHeight: CGFloat = 72
let bodyLabelHeight = bodyLabelSize.height.clamp(0, maxBodyLabelHeight)
let authorLabelHeight: CGFloat = 14.33
let isAuthorShown = isGroupThread
let contentViewHeight: CGFloat
if hasAttachments {
contentViewHeight = thumbnailSize + 8
contentViewHeight = thumbnailSize + 8 // Add a small amount of spacing above and below the thumbnail
} else {
contentViewHeight = bodyLabelHeight + 2 * smallSpacing + (isAuthorShown ? (authorLabelHeight + labelStackViewSpacing) : 0)
if isGroupThread {
contentViewHeight = bodyLabelHeight + (authorLabelHeight + labelStackViewSpacing) + 2 * labelStackViewVMargin
} else {
contentViewHeight = bodyLabelHeight + 2 * smallSpacing
}
}
contentView.set(.height, to: contentViewHeight)
lineView.set(.height, to: contentViewHeight - 8)
lineView.set(.height, to: contentViewHeight - 8) // Add a small amount of spacing above and below the line
}
}

@ -218,16 +218,17 @@ final class VisibleMessageCell : MessageCell {
switch viewItem.messageCellType {
case .textOnlyMessage:
guard let message = viewItem.interaction as? TSMessage else { return }
let inset: CGFloat = 12
// Stack view
let stackView = UIStackView(arrangedSubviews: [])
stackView.axis = .vertical
stackView.spacing = 2
// Quote label
if viewItem.quotedReply != nil {
let maxMessageWidth = VisibleMessageCell.getMaxWidth(for: viewItem)
let maxWidth = VisibleMessageCell.getMaxWidth(for: viewItem) - 2 * inset
let direction: QuoteView.Direction = isOutgoing ? .outgoing : .incoming
let hInset: CGFloat = 2
let quoteView = QuoteView(for: viewItem, direction: direction, hInset: hInset, maxMessageWidth: maxMessageWidth)
let quoteView = QuoteView(for: viewItem, direction: direction, hInset: hInset, maxWidth: maxWidth)
let quoteViewContainer = UIView(wrapping: quoteView, withInsets: UIEdgeInsets(top: 0, leading: hInset, bottom: 0, trailing: hInset))
stackView.addArrangedSubview(quoteViewContainer)
}
@ -241,7 +242,7 @@ final class VisibleMessageCell : MessageCell {
stackView.addArrangedSubview(bodyLabel)
// Constraints
snContentView.addSubview(stackView)
stackView.pin(to: snContentView, withInset: 12)
stackView.pin(to: snContentView, withInset: inset)
case .mediaMessage:
guard let cache = delegate?.getMediaCache() else { preconditionFailure() }
let maxMessageWidth = VisibleMessageCell.getMaxWidth(for: viewItem)

Loading…
Cancel
Save