Ver código fonte

apply colored background containers to messages

cyberta 5 anos atrás
pai
commit
fa0ac62b12

+ 4 - 0
DcCore/DcCore/DC/Wrapper.swift

@@ -837,6 +837,10 @@ public class DcMsg {
         DcContact(id: fromContactId)
     }()
 
+    public var isFromCurrentSender: Bool {
+        return fromContact.id == DcContact(id: Int(DC_CONTACT_ID_SELF)).id
+    }
+
     public var chatId: Int {
         return Int(dc_msg_get_chat_id(messagePointer))
     }

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

@@ -116,6 +116,7 @@
 		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 */; };
+		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 */; };
 		30FDB71F24D8170E0066C48D /* NewTextMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30FDB71E24D8170E0066C48D /* NewTextMessageCell.swift */; };
@@ -403,6 +404,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>"; };
+		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>"; };
 		30FDB71E24D8170E0066C48D /* NewTextMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTextMessageCell.swift; sourceTree = "<group>"; };
@@ -786,6 +788,7 @@
 			isa = PBXGroup;
 			children = (
 				30FDB6B624D193DD0066C48D /* Cells */,
+				30F8817524DA97DA0023780E /* BackgroundContainer.swift */,
 			);
 			path = Views;
 			sourceTree = "<group>";
@@ -1514,6 +1517,7 @@
 				305961E22346125100C80F33 /* MessagesDisplayDelegate.swift in Sources */,
 				305962092346125100C80F33 /* AudioMessageSizeCalculator.swift in Sources */,
 				305961DB2346125100C80F33 /* AudioItem.swift in Sources */,
+				30F8817624DA97DA0023780E /* BackgroundContainer.swift in Sources */,
 				30B0ACFA24AB5B99004D5E29 /* SettingsEphemeralMessageController.swift in Sources */,
 				305962012346125100C80F33 /* PlayButtonView.swift in Sources */,
 				308FEA4C2462F11300FCEAD6 /* FileView.swift in Sources */,

+ 58 - 1
deltachat-ios/Chat/ChatViewControllerNew.swift

@@ -116,6 +116,7 @@ class ChatViewControllerNew: UITableViewController {
 
         tableView.register(NewTextMessageCell.self, forCellReuseIdentifier: "text")
         tableView.rowHeight = UITableView.automaticDimension
+        tableView.separatorStyle = .none
         //messagesCollectionView.register(InfoMessageCell.self)
         super.viewDidLoad()
         if !dcContext.isConfigured() {
@@ -306,7 +307,8 @@ class ChatViewControllerNew: UITableViewController {
 
 
         let cell = tableView.dequeueReusableCell(withIdentifier: "text", for: indexPath) as? NewTextMessageCell ?? NewTextMessageCell()
-        cell.update(msg: message)
+        cell.update(msg: message,
+                    messageStyle: configureMessageStyle(for: message, at: indexPath))
         return cell
     }
 
@@ -314,6 +316,61 @@ class ChatViewControllerNew: UITableViewController {
         return "test title" //viewModel.titleForHeaderIn(section: section)
     }
 
+    func configureMessageStyle(for message: DcMsg, at indexPath: IndexPath) -> UIRectCorner {
+
+        var corners: UIRectCorner = []
+
+        if message.isFromCurrentSender { //isFromCurrentSender(message: message) {
+            corners.formUnion(.topLeft)
+            corners.formUnion(.bottomLeft)
+            if !isPreviousMessageSameSender(currentMessage: message, at: indexPath) {
+                corners.formUnion(.topRight)
+            }
+            if !isNextMessageSameSender(currentMessage: message, at: indexPath) {
+                corners.formUnion(.bottomRight)
+            }
+        } else {
+            corners.formUnion(.topRight)
+            corners.formUnion(.bottomRight)
+            if !isPreviousMessageSameSender(currentMessage: message, at: indexPath) {
+                corners.formUnion(.topLeft)
+            }
+            if !isNextMessageSameSender(currentMessage: message, at: indexPath) {
+                corners.formUnion(.bottomLeft)
+            }
+        }
+
+        return corners
+    }
+
+    private func getBackgroundColor(for currentMessage: DcMsg) -> UIColor {
+        return currentMessage.isFromCurrentSender ? DcColors.messagePrimaryColor : DcColors.messageSecondaryColor
+    }
+
+    private func isPreviousMessageSameSender(currentMessage: DcMsg, at indexPath: IndexPath) -> Bool {
+        let previousRow = indexPath.row - 1
+        if previousRow < 0 {
+            return false
+        }
+
+        let messageId = messageIds[previousRow]
+        let previousMessage = DcMsg(id: messageId)
+
+        return previousMessage.fromContact.id == currentMessage.fromContact.id
+    }
+
+    private func isNextMessageSameSender(currentMessage: DcMsg, at indexPath: IndexPath) -> Bool {
+        let nextRow = indexPath.row + 1
+        if nextRow >= messageIds.count {
+            return false
+        }
+
+        let messageId = messageIds[nextRow]
+        let nextMessage = DcMsg(id: messageId)
+
+        return nextMessage.fromContact.id == currentMessage.fromContact.id
+    }
+
 
     private func updateTitle(chat: DcChat) {
         let titleView =  ChatTitleView()

+ 38 - 0
deltachat-ios/Chat/Views/BackgroundContainer.swift

@@ -0,0 +1,38 @@
+
+
+import Foundation
+import UIKit
+import DcCore
+
+class BackgroundContainer: UIImageView {
+
+    var rectCorners: UIRectCorner?
+
+    func update(rectCorners: UIRectCorner, color: UIColor) {
+        self.rectCorners = rectCorners
+        image = UIImage(color: color)
+        setNeedsLayout()
+        layoutIfNeeded()
+    }
+
+    override func layoutSubviews() {
+        super.layoutSubviews()
+        applyPath()
+    }
+
+    func applyPath() {
+        let radius: CGFloat = 16
+        let path = UIBezierPath(roundedRect: bounds,
+                                byRoundingCorners: rectCorners ?? UIRectCorner(),
+                                cornerRadii: CGSize(width: radius, height: radius))
+        let mask = CAShapeLayer()
+        mask.path = path.cgPath
+        layer.mask = mask
+    }
+
+    func prepareForReuse() {
+        layer.mask = nil
+        image = nil
+    }
+
+}

+ 29 - 10
deltachat-ios/Chat/Views/Cells/BaseMessageCell.swift

@@ -3,6 +3,8 @@ import DcCore
 public class BaseMessageCell: UITableViewCell {
 
     static var defaultPadding: CGFloat = 12
+    static var containerPadding: CGFloat = -6
+    typealias BMC = BaseMessageCell
 
     lazy var avatarView: InitialsBadge = {
         let view = InitialsBadge(size: 28)
@@ -32,6 +34,7 @@ public class BaseMessageCell: UITableViewCell {
         view.axis = .horizontal
         return view
     }()
+
     lazy var bottomLabel: UILabel = {
         let label = UILabel()
         label.translatesAutoresizingMaskIntoConstraints = false
@@ -46,6 +49,15 @@ public class BaseMessageCell: UITableViewCell {
         return view
     }()
 
+    private lazy var messageBackgroundContainer: BackgroundContainer = {
+        let container = BackgroundContainer()
+        container.image = UIImage(color: UIColor.blue)
+        container.contentMode = .scaleToFill
+        container.clipsToBounds = true
+        container.translatesAutoresizingMaskIntoConstraints = false
+        return container
+    }()
+
     override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
         super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
         setupSubviews()
@@ -58,23 +70,31 @@ public class BaseMessageCell: UITableViewCell {
 
     func setupSubviews() {
         contentView.addSubview(avatarView)
+        contentView.addSubview(messageBackgroundContainer)
         contentView.addSubview(contentContainer)
 
         contentView.addConstraints([
-            avatarView.constraintAlignTopTo(contentView, paddingTop: defaultPadding),
+            avatarView.constraintAlignTopTo(contentView, paddingTop: BMC.defaultPadding),
             avatarView.constraintAlignLeadingTo(contentView),
-            avatarView.constraintAlignBottomTo(contentView, paddingBottom: defaultPadding, priority: .defaultLow),
-            contentContainer.constraintToTrailingOf(avatarView, paddingLeading: defaultPadding),
-            contentContainer.constraintAlignTrailingTo(contentView, paddingTrailing: defaultPadding),
-            contentContainer.constraintAlignTopTo(contentView, paddingTop: defaultPadding),
-            contentContainer.constraintAlignBottomTo(contentView, paddingBottom: defaultPadding)
+            avatarView.constraintAlignBottomTo(contentView, paddingBottom: BMC.defaultPadding, priority: .defaultLow),
+            contentContainer.constraintToTrailingOf(avatarView, paddingLeading: BMC.defaultPadding),
+            contentContainer.constraintAlignTrailingTo(contentView, paddingTrailing: BMC.defaultPadding),
+            contentContainer.constraintAlignTopTo(contentView, paddingTop: BMC.defaultPadding),
+            contentContainer.constraintAlignBottomTo(contentView, paddingBottom: BMC.defaultPadding),
+            messageBackgroundContainer.constraintAlignLeadingTo(contentContainer, paddingLeading: BMC.containerPadding),
+            messageBackgroundContainer.constraintAlignTopTo(contentContainer, paddingTop: BMC.containerPadding),
+            messageBackgroundContainer.constraintAlignBottomTo(contentContainer, paddingBottom: BMC.containerPadding),
+            messageBackgroundContainer.constraintAlignTrailingTo(contentContainer, paddingTrailing: BMC.containerPadding)
         ])
     }
-    
-    func update(msg: DcMsg) {
+
+
+    // update classes inheriting BaseMessageCell first before calling super.update(...)
+    func update(msg: DcMsg, messageStyle: UIRectCorner) {
         topLabel.text = msg.fromContact.displayName
         avatarView.setName(msg.fromContact.displayName)
         avatarView.setColor(msg.fromContact.color)
+        messageBackgroundContainer.update(rectCorners: messageStyle, color: msg.isFromCurrentSender ? DcColors.messagePrimaryColor : DcColors.messageSecondaryColor)
     }
 
     override public func prepareForReuse() {
@@ -82,7 +102,6 @@ public class BaseMessageCell: UITableViewCell {
         textLabel?.attributedText = nil
         topLabel.text = nil
         avatarView.reset()
-
+        messageBackgroundContainer.prepareForReuse()
     }
-    
 }

+ 3 - 2
deltachat-ios/Chat/Views/Cells/NewTextMessageCell.swift

@@ -16,11 +16,12 @@ class NewTextMessageCell: BaseMessageCell {
         super.setupSubviews()
         mainContentView.addArrangedSubview(messageLabel)
         mainContentView.axis = .horizontal
+        
     }
 
-    override func update(msg: DcMsg) {
-        super.update(msg: msg)
+    override func update(msg: DcMsg, messageStyle: UIRectCorner) {
         messageLabel.text = msg.text
+        super.update(msg: msg, messageStyle: messageStyle)
     }
 
     override func prepareForReuse() {