Pārlūkot izejas kodu

allow selection of info messages (#1614)

* allow to multi-select info messages

* hide forwarding option if any info message was selected

* fix layout issues for InfoMessageCells in multi-select mode by dynamically adapting padding
cyBerta 2 gadi atpakaļ
vecāks
revīzija
4d85cbe90d

+ 19 - 8
deltachat-ios/Chat/ChatViewController.swift

@@ -728,6 +728,7 @@ class ChatViewController: UITableViewController {
         let message = dcContext.getMessage(id: id)
         if message.isInfo {
             let cell = tableView.dequeueReusableCell(withIdentifier: "info", for: indexPath) as? InfoMessageCell ?? InfoMessageCell()
+            cell.showSelectionBackground(tableView.isEditing)
             cell.update(text: message.text)
             return cell
         }
@@ -914,8 +915,12 @@ class ChatViewController: UITableViewController {
     }
 
     override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
-        if let cell = tableView.cellForRow(at: indexPath) as? SelectableCell {
-            cell.showSelectionBackground(tableView.isEditing)
+        let tableViewCell = tableView.cellForRow(at: indexPath)
+        if let selectableCell = tableViewCell as? SelectableCell,
+           !(tableView.isEditing &&
+             tableViewCell as? InfoMessageCell != nil &&
+             messageIds[indexPath.row] <= DC_MSG_ID_LAST_SPECIAL) {
+            selectableCell.showSelectionBackground(tableView.isEditing)
             return indexPath
         }
         return nil
@@ -1859,10 +1864,8 @@ class ChatViewController: UITableViewController {
         if tableView.isEditing {
             if tableView.indexPathsForSelectedRows?.contains(indexPath) ?? false {
                 tableView.deselectRow(at: indexPath, animated: false)
-            } else {
-                if let cell = tableView.cellForRow(at: indexPath) as? SelectableCell {
-                    cell.showSelectionBackground(true)
-                }
+            } else if let cell = tableView.cellForRow(at: indexPath) as? SelectableCell {
+                cell.showSelectionBackground(true)
                 tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
             }
             handleEditingBar()
@@ -1872,9 +1875,17 @@ class ChatViewController: UITableViewController {
     }
 
     func handleEditingBar() {
-        if let rows = tableView.indexPathsForSelectedRows,
-           !rows.isEmpty {
+        if let indexPaths = tableView.indexPathsForSelectedRows,
+           !indexPaths.isEmpty {
+            var hasInfoMessageSelected = false
+            for indexPath in indexPaths {
+                if dcContext.getMessage(id: messageIds[indexPath.row]).isInfo {
+                    hasInfoMessageSelected = true
+                    break
+                }
+            }
             editingBar.isEnabled = true
+            editingBar.forwardButton.isHidden = hasInfoMessageSelected
         } else {
             editingBar.isEnabled = false
         }

+ 44 - 5
deltachat-ios/Chat/Views/Cells/InfoMessageCell.swift

@@ -3,6 +3,10 @@ import DcCore
 
 class InfoMessageCell: UITableViewCell {
 
+    private var showSelectionBackground: Bool
+    private var trailingConstraint: NSLayoutConstraint?
+    private var trailingConstraintEditingMode: NSLayoutConstraint?
+
     private lazy var messageBackgroundContainer: BackgroundContainer = {
         let container = BackgroundContainer()
         container.image = UIImage(color: DcColors.systemMessageBackgroundColor)
@@ -23,6 +27,7 @@ class InfoMessageCell: UITableViewCell {
     }()
 
     override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+        self.showSelectionBackground = false
         super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
         clipsToBounds = false
         backgroundColor = .clear
@@ -40,15 +45,18 @@ class InfoMessageCell: UITableViewCell {
         contentView.addConstraints([
             messageLabel.constraintAlignTopTo(contentView, paddingTop: 12),
             messageLabel.constraintAlignBottomTo(contentView, paddingBottom: 12),
-            messageLabel.constraintAlignLeadingMaxTo(contentView, paddingLeading: 50),
-            messageLabel.constraintAlignTrailingMaxTo(contentView, paddingTrailing: 50),
-            messageLabel.constraintCenterXTo(contentView),
+            messageLabel.constraintAlignLeadingMaxTo(contentView, paddingLeading: 55),
+            messageLabel.constraintCenterXTo(contentView, priority: .defaultLow),
             messageBackgroundContainer.constraintAlignLeadingTo(messageLabel, paddingLeading: -6),
             messageBackgroundContainer.constraintAlignTopTo(messageLabel, paddingTop: -6),
             messageBackgroundContainer.constraintAlignBottomTo(messageLabel, paddingBottom: -6),
             messageBackgroundContainer.constraintAlignTrailingTo(messageLabel, paddingTrailing: -6)
         ])
-        selectionStyle = .none
+
+        trailingConstraint = messageLabel.constraintAlignTrailingMaxTo(contentView, paddingTrailing: 55)
+        trailingConstraintEditingMode = messageLabel.constraintAlignTrailingMaxTo(contentView, paddingTrailing: 10)
+        trailingConstraint?.isActive = !isEditing
+        trailingConstraintEditingMode?.isActive = isEditing
     }
 
     func update(text: String?, weight: UIFont.Weight? = nil) {
@@ -64,16 +72,47 @@ class InfoMessageCell: UITableViewCell {
         corners.formUnion(.topRight)
         corners.formUnion(.bottomRight)
         messageBackgroundContainer.update(rectCorners: corners, color: DcColors.systemMessageBackgroundColor)
+        trailingConstraint?.isActive = !isEditing
+        trailingConstraintEditingMode?.isActive = isEditing
     }
 
     override func prepareForReuse() {
         super.prepareForReuse()
         messageLabel.text = nil
         messageLabel.attributedText = nil
+        showSelectionBackground = false
+    }
+    
+    public override func willTransition(to state: UITableViewCell.StateMask) {
+        super.willTransition(to: state)
+        // while the content view gets intended by the appearance of the edit control,
+        // we're adapting the the padding of the messages on the left side of the screen
+        if state == .showingEditControl {
+            if trailingConstraint?.isActive ?? false {
+                trailingConstraint?.isActive = false
+                trailingConstraintEditingMode?.isActive = true
+            }
+        } else {
+            if trailingConstraintEditingMode?.isActive ?? false {
+                trailingConstraintEditingMode?.isActive = false
+                trailingConstraint?.isActive = true
+            }
+        }
     }
 
+    public override func setSelected(_ selected: Bool, animated: Bool) {
+         super.setSelected(selected, animated: animated)
+         if selected && showSelectionBackground {
+             selectedBackgroundView?.backgroundColor = DcColors.chatBackgroundColor.withAlphaComponent(0.5)
+         } else {
+             selectedBackgroundView?.backgroundColor = .clear
+         }
+     }
 }
 
 extension InfoMessageCell: SelectableCell {
-    public func showSelectionBackground(_ show: Bool) {}
+    public func showSelectionBackground(_ show: Bool) {
+        selectionStyle = show ? .default : .none
+        showSelectionBackground = show
+    }
 }

+ 2 - 2
deltachat-ios/Chat/Views/ChatEditingBar.swift

@@ -35,7 +35,7 @@ public class ChatEditingBar: UIView, InputItem {
         return view
     }()
 
-    private lazy var deleteButton: UIButton = {
+    public lazy var deleteButton: UIButton = {
         let view = UIButton()
 
         if #available(iOS 13.0, *) {
@@ -52,7 +52,7 @@ public class ChatEditingBar: UIView, InputItem {
         return view
     }()
 
-    private lazy var forwardButton: UIButton = {
+    public lazy var forwardButton: UIButton = {
         let view = UIButton()
         view.tintColor = .systemBlue
         view.setImage( #imageLiteral(resourceName: "ic_forward_white_36pt").withRenderingMode(.alwaysTemplate), for: .normal)