Pārlūkot izejas kodu

improve cell layout for images, tweak paddings here and there

cyberta 4 gadi atpakaļ
vecāks
revīzija
21afbfea7b

+ 6 - 0
deltachat-ios.xcodeproj/project.pbxproj

@@ -124,6 +124,8 @@
 		30E8F2442449C64100CE2C90 /* ChatListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E8F2432449C64100CE2C90 /* ChatListCell.swift */; };
 		30E8F2512449EA0E00CE2C90 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3060119E22DDE24000C1CE6F /* Localizable.strings */; };
 		30E8F253244DAD0E00CE2C90 /* SendingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E8F252244DAD0E00CE2C90 /* SendingController.swift */; };
+		30F4BFEE252E3E020006B9B3 /* PaddingLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30F4BFED252E3E020006B9B3 /* PaddingLabel.swift */; };
+		30F4C002252E43510006B9B3 /* PaddingLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30F4BFED252E3E020006B9B3 /* PaddingLabel.swift */; };
 		30F8817624DA97DA0023780E /* BackgroundContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30F8817524DA97DA0023780E /* BackgroundContainer.swift */; };
 		30F9B9EC235F2116006E7ACF /* MessageCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30F9B9EB235F2116006E7ACF /* MessageCounter.swift */; };
 		30FDB70524D1C1000066C48D /* ChatViewControllerNew.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30FDB6F824D1C1000066C48D /* ChatViewControllerNew.swift */; };
@@ -420,6 +422,7 @@
 		30E8F2412448B77600CE2C90 /* ChatListController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListController.swift; sourceTree = "<group>"; };
 		30E8F2432449C64100CE2C90 /* ChatListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListCell.swift; sourceTree = "<group>"; };
 		30E8F252244DAD0E00CE2C90 /* SendingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendingController.swift; sourceTree = "<group>"; };
+		30F4BFED252E3E020006B9B3 /* PaddingLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaddingLabel.swift; sourceTree = "<group>"; };
 		30F8817524DA97DA0023780E /* BackgroundContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundContainer.swift; sourceTree = "<group>"; };
 		30F9B9EB235F2116006E7ACF /* MessageCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageCounter.swift; sourceTree = "<group>"; };
 		30FDB6F824D1C1000066C48D /* ChatViewControllerNew.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatViewControllerNew.swift; sourceTree = "<group>"; };
@@ -1057,6 +1060,7 @@
 				AEFBE22E23FEF23D0045327A /* ProviderInfoCell.swift */,
 				AEB54C7E246DBA610004624C /* FlexLabel.swift */,
 				AED62BCD247687E6009E220D /* LocationStreamingIndicator.swift */,
+				30F4BFED252E3E020006B9B3 /* PaddingLabel.swift */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -1425,6 +1429,7 @@
 				30E8F253244DAD0E00CE2C90 /* SendingController.swift in Sources */,
 				3057028C24C5E7B600D84EFC /* ContactCellViewModel.swift in Sources */,
 				30E8F2422448B77600CE2C90 /* ChatListController.swift in Sources */,
+				30F4C002252E43510006B9B3 /* PaddingLabel.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1468,6 +1473,7 @@
 				AE8DD451249D1DFB009A4BC1 /* FileTableViewCell.swift in Sources */,
 				3040F45E234DFBC000FA34D5 /* Audio.swift in Sources */,
 				305961FE2346125100C80F33 /* InsetLabel.swift in Sources */,
+				30F4BFEE252E3E020006B9B3 /* PaddingLabel.swift in Sources */,
 				3095A351237DD1F700AB07F7 /* MediaPicker.swift in Sources */,
 				B21005DB23383664004C70C5 /* SettingsClassicViewController.swift in Sources */,
 				305961F62346125100C80F33 /* MessageContentCell.swift in Sources */,

+ 102 - 44
deltachat-ios/Chat/Views/Cells/BaseMessageCell.swift

@@ -3,26 +3,73 @@ import DcCore
 
 public class BaseMessageCell: UITableViewCell {
 
-    static var defaultPadding: CGFloat = 12
-    static var containerPadding: CGFloat = -6
-    typealias BMC = BaseMessageCell
-
     private var leadingConstraint: NSLayoutConstraint?
     private var trailingConstraint: NSLayoutConstraint?
     private var leadingConstraintCurrentSender: NSLayoutConstraint?
     private var trailingConstraintCurrentSender: NSLayoutConstraint?
+    private var mainContentBelowTopLabelConstraint: NSLayoutConstraint?
+    private var mainContentUnderTopLabelConstraint: NSLayoutConstraint?
+    private var mainContentAboveBottomLabelConstraint: NSLayoutConstraint?
+    private var mainContentUnderBottomLabelConstraint: NSLayoutConstraint?
+    private var bottomLineLeftAlignedConstraint: [NSLayoutConstraint] = []
+    private var bottomLineRightAlignedConstraint: [NSLayoutConstraint] = []
+    private var mainContentViewLeadingConstraint: NSLayoutConstraint?
+    private var mainContentViewTrailingConstraint: NSLayoutConstraint?
+
+    public var mainContentViewHorizontalPadding: CGFloat {
+        set {
+            mainContentViewLeadingConstraint?.constant = newValue
+            mainContentViewTrailingConstraint?.constant = -newValue
+        }
+        get {
+            return mainContentViewLeadingConstraint?.constant ?? 0
+        }
+    }
 
-    public weak var baseDelegate: BaseMessageCellDelegate?
+    //aligns the bottomLabel to the left / right
+    private var bottomLineLeftAlign: Bool {
+        set {
+            for constraint in bottomLineLeftAlignedConstraint {
+                constraint.isActive = newValue
+            }
+            for constraint in bottomLineRightAlignedConstraint {
+                constraint.isActive = !newValue
+            }
+        }
+        get {
+            return !bottomLineLeftAlignedConstraint.isEmpty && bottomLineLeftAlignedConstraint[0].isActive
+        }
+    }
 
-    private lazy var contentContainer: UIStackView = {
-        let view = UIStackView(arrangedSubviews: [topLabel, mainContentView, bottomContentView])
-        view.translatesAutoresizingMaskIntoConstraints = false
-        view.setContentHuggingPriority(.defaultLow, for: .horizontal)
-        view.alignment = .leading
-        view.axis = .vertical
-        view.spacing = 6
-        return view
-    }()
+    // if set to true topLabel overlaps the main content
+    public var topCompactView: Bool {
+        set {
+            mainContentBelowTopLabelConstraint?.isActive = !newValue
+            mainContentUnderTopLabelConstraint?.isActive = newValue
+            topLabel.backgroundColor = newValue ?
+                UIColor(alpha: 200, red: 50, green: 50, blue: 50) :
+                UIColor(alpha: 0, red: 0, green: 0, blue: 0)
+        }
+        get {
+            return mainContentUnderTopLabelConstraint?.isActive ?? false
+        }
+    }
+
+    // if set to true bottomLabel overlaps the main content
+    public var bottomCompactView: Bool {
+        set {
+            mainContentAboveBottomLabelConstraint?.isActive = !newValue
+            mainContentUnderBottomLabelConstraint?.isActive = newValue
+            bottomLabel.backgroundColor = newValue ?
+                UIColor(alpha: 200, red: 50, green: 50, blue: 50) :
+                UIColor(alpha: 0, red: 0, green: 0, blue: 0)
+        }
+        get {
+            return mainContentUnderBottomLabelConstraint?.isActive ?? false
+        }
+    }
+
+    public weak var baseDelegate: BaseMessageCellDelegate?
 
     lazy var avatarView: InitialsBadge = {
         let view = InitialsBadge(size: 28)
@@ -34,10 +81,12 @@ public class BaseMessageCell: UITableViewCell {
     }()
 
     lazy var topLabel: UILabel = {
-        let label = UILabel()
+        let label = PaddingLabel(top: 0, left: 4, bottom: 0, right: 4)
         label.translatesAutoresizingMaskIntoConstraints = false
         label.text = "title"
         label.font = UIFont.preferredFont(for: .caption1, weight: .regular)
+        label.layer.cornerRadius = 4
+        label.clipsToBounds = true
         return label
     }()
 
@@ -48,25 +97,14 @@ public class BaseMessageCell: UITableViewCell {
         return view
     }()
 
-    var bottomSpacerConstraint: NSLayoutConstraint?
-    lazy var bottomContentView: UIStackView = {
-        let stretchingView = UIView()
-        bottomSpacerConstraint = stretchingView.constraintWidthTo(10000, priority: .defaultLow)
-        stretchingView.setContentHuggingPriority(.defaultLow, for: .horizontal)
-        stretchingView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
-        let view = UIStackView(arrangedSubviews: [stretchingView, bottomLabel])
-        view.translatesAutoresizingMaskIntoConstraints = false
-        view.axis = .horizontal
-        view.distribution = .fill
-        return view
-    }()
-
     lazy var bottomLabel: UILabel = {
-        let label = UILabel()
+        let label = PaddingLabel(top: 0, left: 4, bottom: 0, right: 4)
         label.translatesAutoresizingMaskIntoConstraints = false
         label.font = UIFont.preferredFont(for: .caption1, weight: .regular)
         label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
         label.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
+        label.layer.cornerRadius = 4
+        label.clipsToBounds = true
         return label
     }()
 
@@ -76,6 +114,7 @@ public class BaseMessageCell: UITableViewCell {
         container.contentMode = .scaleToFill
         container.clipsToBounds = true
         container.translatesAutoresizingMaskIntoConstraints = false
+        container.isUserInteractionEnabled = true
         return container
     }()
 
@@ -93,26 +132,46 @@ public class BaseMessageCell: UITableViewCell {
 
     func setupSubviews() {
         contentView.addSubview(messageBackgroundContainer)
-        contentView.addSubview(contentContainer)
+        messageBackgroundContainer.addSubview(mainContentView)
+        messageBackgroundContainer.addSubview(topLabel)
+        messageBackgroundContainer.addSubview(bottomLabel)
         contentView.addSubview(avatarView)
 
         contentView.addConstraints([
-            avatarView.constraintAlignTopTo(contentView, paddingTop: BMC.defaultPadding, priority: .defaultLow),
             avatarView.constraintAlignLeadingTo(contentView, paddingLeading: 6),
             avatarView.constraintAlignBottomTo(contentView, paddingBottom: -6),
-            contentContainer.constraintAlignTopTo(contentView, paddingTop: BMC.defaultPadding),
-            contentContainer.constraintAlignBottomTo(contentView, paddingBottom: BMC.defaultPadding),
-            messageBackgroundContainer.constraintAlignLeadingTo(contentContainer, paddingLeading: 2 * BMC.containerPadding),
-            messageBackgroundContainer.constraintAlignTopTo(contentContainer, paddingTop: BMC.containerPadding),
-            messageBackgroundContainer.constraintAlignBottomTo(contentContainer, paddingBottom: BMC.containerPadding),
-            messageBackgroundContainer.constraintAlignTrailingTo(contentContainer, paddingTrailing: BMC.containerPadding)
+            avatarView.constraintWidthTo(28, priority: .defaultHigh),
+            avatarView.constraintHeightTo(28, priority: .defaultHigh),
+            topLabel.constraintAlignTopTo(messageBackgroundContainer, paddingTop: 6),
+            topLabel.constraintAlignLeadingTo(messageBackgroundContainer, paddingLeading: 6),
+            topLabel.constraintAlignTrailingMaxTo(messageBackgroundContainer, paddingTrailing: 6),
+            bottomLabel.constraintAlignBottomTo(messageBackgroundContainer, paddingBottom: 6),
+            messageBackgroundContainer.constraintAlignTopTo(contentView, paddingTop: 6),
+            messageBackgroundContainer.constraintAlignBottomTo(contentView),
         ])
 
-        leadingConstraint = contentContainer.constraintToTrailingOf(avatarView)
-        trailingConstraint = contentContainer.constraintAlignTrailingMaxTo(contentView, paddingTrailing: BMC.defaultPadding)
-        leadingConstraintCurrentSender = contentContainer.constraintAlignLeadingMaxTo(contentView, paddingLeading: 36)
-        trailingConstraintCurrentSender = contentContainer.constraintAlignTrailingTo(contentView, paddingTrailing: BMC.defaultPadding)
+        leadingConstraint = messageBackgroundContainer.constraintToTrailingOf(avatarView, paddingLeading: -8)
+        trailingConstraint = messageBackgroundContainer.constraintAlignTrailingMaxTo(contentView, paddingTrailing: 36)
+        leadingConstraintCurrentSender = messageBackgroundContainer.constraintAlignLeadingMaxTo(contentView, paddingLeading: 36)
+        trailingConstraintCurrentSender = messageBackgroundContainer.constraintAlignTrailingTo(contentView, paddingTrailing: 6)
+
+        mainContentViewLeadingConstraint = mainContentView.constraintAlignLeadingTo(messageBackgroundContainer)
+        mainContentViewTrailingConstraint = mainContentView.constraintAlignTrailingTo(messageBackgroundContainer)
+        mainContentViewLeadingConstraint?.isActive = true
+        mainContentViewTrailingConstraint?.isActive = true
 
+        mainContentBelowTopLabelConstraint = mainContentView.constraintToBottomOf(topLabel, paddingTop: 6)
+        mainContentUnderTopLabelConstraint = mainContentView.constraintAlignTopTo(messageBackgroundContainer)
+        mainContentAboveBottomLabelConstraint = bottomLabel.constraintToBottomOf(mainContentView, paddingTop: 6, priority: .defaultHigh)
+        mainContentUnderBottomLabelConstraint = mainContentView.constraintAlignBottomTo(messageBackgroundContainer, paddingBottom: 0, priority: .defaultHigh)
+
+        bottomLineRightAlignedConstraint = [bottomLabel.constraintAlignLeadingMaxTo(messageBackgroundContainer, paddingLeading: 6),
+                                           bottomLabel.constraintAlignTrailingTo(messageBackgroundContainer, paddingTrailing: 6)]
+        bottomLineLeftAlignedConstraint = [bottomLabel.constraintAlignLeadingTo(messageBackgroundContainer, paddingLeading: 6),
+                                           bottomLabel.constraintAlignTrailingMaxTo(messageBackgroundContainer, paddingTrailing: 6)]
+
+        topCompactView = false
+        bottomCompactView = false
         selectionStyle = .none
     }
 
@@ -122,18 +181,17 @@ public class BaseMessageCell: UITableViewCell {
             topLabel.text = nil
             leadingConstraintCurrentSender?.isActive = true
             trailingConstraintCurrentSender?.isActive = true
-            bottomSpacerConstraint?.isActive = true
             leadingConstraint?.isActive = false
             trailingConstraint?.isActive = false
+            bottomLineLeftAlign = false
 
         } else {
             topLabel.text = isGroup ? msg.fromContact.displayName : nil
             leadingConstraint?.isActive = true
             trailingConstraint?.isActive = true
-            bottomSpacerConstraint?.isActive = false
             leadingConstraintCurrentSender?.isActive = false
             trailingConstraintCurrentSender?.isActive = false
-
+            bottomLineLeftAlign = true
         }
 
         if isAvatarVisible {

+ 1 - 1
deltachat-ios/Chat/Views/Cells/NewAudioMessageCell.swift

@@ -18,7 +18,7 @@ public class NewAudioMessageCell: BaseMessageCell {
     }()
 
     lazy var messageLabel: UILabel = {
-        let label = UILabel()
+        let label = PaddingLabel(top: 0, left: 12, bottom: 0, right: 12)
         label.translatesAutoresizingMaskIntoConstraints = false
         label.numberOfLines = 0
         label.lineBreakMode = .byWordWrapping

+ 3 - 1
deltachat-ios/Chat/Views/Cells/NewFileTextCell.swift

@@ -20,10 +20,12 @@ class NewFileTextCell: BaseMessageCell {
                 fileStackView.axis = .horizontal
                 imageWidthConstraint?.isActive = true
                 imageHeightConstraint?.isActive = true
+                fileStackView.alignment = .center
             } else {
                 fileStackView.axis = .vertical
                 imageWidthConstraint?.isActive = false
                 imageHeightConstraint?.isActive = false
+                fileStackView.alignment = .leading
             }
         }
         get {
@@ -35,7 +37,6 @@ class NewFileTextCell: BaseMessageCell {
         let stackView = UIStackView(arrangedSubviews: [fileImageView, fileMetadataStackView])
         stackView.axis = .horizontal
         stackView.spacing = 6
-        stackView.alignment = .center
         return stackView
     }()
 
@@ -91,6 +92,7 @@ class NewFileTextCell: BaseMessageCell {
         imageWidthConstraint = fileImageView.constraintWidthTo(50)
         imageHeightConstraint = fileImageView.constraintHeightTo(50 * 1.3, priority: .defaultLow)
         horizontalLayout = true
+        mainContentViewHorizontalPadding = 12
     }
 
     override func prepareForReuse() {

+ 4 - 1
deltachat-ios/Chat/Views/Cells/NewImageTextCell.swift

@@ -9,7 +9,7 @@ class NewImageTextCell: BaseMessageCell {
     var imageWidthConstraint: NSLayoutConstraint?
 
     lazy var messageLabel: UILabel = {
-        let label = UILabel()
+        let label = PaddingLabel(top: 0, left: 12, bottom: 0, right: 12)
         label.translatesAutoresizingMaskIntoConstraints = false
         label.numberOfLines = 0
         label.lineBreakMode = .byWordWrapping
@@ -46,6 +46,7 @@ class NewImageTextCell: BaseMessageCell {
         mainContentView.addArrangedSubview(messageLabel)
         contentImageView.constraintAlignLeadingMaxTo(mainContentView).isActive = true
         contentImageView.constraintAlignTrailingMaxTo(mainContentView).isActive = true
+        topCompactView = true
         let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(onImageTapped))
         gestureRecognizer.numberOfTapsRequired = 1
         contentImageView.addGestureRecognizer(gestureRecognizer)
@@ -53,6 +54,8 @@ class NewImageTextCell: BaseMessageCell {
 
     override func update(msg: DcMsg, messageStyle: UIRectCorner, isAvatarVisible: Bool, isGroup: Bool) {
         messageLabel.text = msg.text
+        bottomCompactView = msg.text?.isEmpty ?? true
+        mainContentView.spacing = msg.text?.isEmpty ?? false ? 0 : 6
         tag = msg.id
         if msg.type == DC_MSG_IMAGE, let image = msg.image {
             contentImageView.image = image

+ 1 - 1
deltachat-ios/Chat/Views/Cells/NewTextMessageCell.swift

@@ -5,7 +5,7 @@ import UIKit
 class NewTextMessageCell: BaseMessageCell {
 
     lazy var messageLabel: UILabel = {
-        let label = UILabel()
+        let label = PaddingLabel(top: 0, left: 12, bottom: 0, right: 12)
         label.translatesAutoresizingMaskIntoConstraints = false
         label.numberOfLines = 0
         label.lineBreakMode = .byWordWrapping

+ 1 - 1
deltachat-ios/Chat/Views/NewAudioPlayerView.swift

@@ -53,7 +53,7 @@ open class NewAudioPlayerView: UIView {
         playButton.constraintWidthTo(45, priority: UILayoutPriority(rawValue: 999)).isActive = true
 
         let playButtonConstraints = [playButton.constraintCenterYTo(self),
-                                     playButton.constraintAlignLeadingTo(self)]
+                                     playButton.constraintAlignLeadingTo(self, paddingLeading: 12)]
         let durationLabelConstraints = [durationLabel.constraintAlignTrailingTo(self, paddingTrailing: 12),
                                         durationLabel.constraintCenterYTo(self)]
         self.addConstraints(playButtonConstraints)

+ 0 - 25
deltachat-ios/View/FlexLabel.swift

@@ -55,29 +55,4 @@ class FlexLabel: UIView {
         label.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor).isActive = true
         label.widthAnchor.constraint(lessThanOrEqualTo: widthAnchor, multiplier: 0.95).isActive = true
     }
-
-    class PaddingLabel: UILabel {
-        let insets: UIEdgeInsets
-
-        init(top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) {
-            self.insets = UIEdgeInsets(top: top, left: left, bottom: bottom, right: right)
-            super.init(frame: .zero)
-        }
-
-        required init?(coder: NSCoder) {
-            fatalError("init(coder:) has not been implemented")
-        }
-
-        override func drawText(in rect: CGRect) {
-            super.drawText(in: rect.inset(by: insets))
-        }
-
-        override var intrinsicContentSize: CGSize {
-            let size = super.intrinsicContentSize
-            return CGSize(
-                width: size.width + insets.left + insets.right,
-                height: size.height + insets.top + insets.bottom
-            )
-        }
-    }
 }

+ 25 - 0
deltachat-ios/View/PaddingLabel.swift

@@ -0,0 +1,25 @@
+import UIKit
+public class PaddingLabel: UILabel {
+    let insets: UIEdgeInsets
+
+    init(top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) {
+        self.insets = UIEdgeInsets(top: top, left: left, bottom: bottom, right: right)
+        super.init(frame: .zero)
+    }
+
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    public override func drawText(in rect: CGRect) {
+        super.drawText(in: rect.inset(by: insets))
+    }
+
+    public override var intrinsicContentSize: CGSize {
+        let size = super.intrinsicContentSize
+        return CGSize(
+            width: size.width + insets.left + insets.right,
+            height: size.height + insets.top + insets.bottom
+        )
+    }
+}