瀏覽代碼

refactorings: implement draft model class, move UI configuration code to QuotePreview class

cyberta 4 年之前
父節點
當前提交
3f5b7bc312

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

@@ -20,6 +20,7 @@
 		302B84CE2397F6CD001C261F /* URL+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302B84CD2397F6CD001C261F /* URL+Extension.swift */; };
 		302E1BB4252B5AB4008F4264 /* PlayButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302E1BB3252B5AB4008F4264 /* PlayButtonView.swift */; };
 		30349291256441E200A523D0 /* QuotePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30349290256441E200A523D0 /* QuotePreview.swift */; };
+		303492952565AABC00A523D0 /* DraftModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 303492942565AABC00A523D0 /* DraftModel.swift */; };
 		304219D3243F588500516852 /* DcCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 304219D1243F588500516852 /* DcCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
 		304219D92440734A00516852 /* DcMsg+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 304219D82440734A00516852 /* DcMsg+Extension.swift */; };
 		304F5E44244F571C00462538 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A9FB14A1FB061E2001FEA36 /* Assets.xcassets */; };
@@ -215,6 +216,7 @@
 		302B84CD2397F6CD001C261F /* URL+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Extension.swift"; sourceTree = "<group>"; };
 		302E1BB3252B5AB4008F4264 /* PlayButtonView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PlayButtonView.swift; path = "deltachat-ios/Chat/Views/PlayButtonView.swift"; sourceTree = SOURCE_ROOT; };
 		30349290256441E200A523D0 /* QuotePreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuotePreview.swift; sourceTree = "<group>"; };
+		303492942565AABC00A523D0 /* DraftModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftModel.swift; sourceTree = "<group>"; };
 		304219D1243F588500516852 /* DcCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DcCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		304219D82440734A00516852 /* DcMsg+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DcMsg+Extension.swift"; sourceTree = "<group>"; };
 		3052C609253F082E007D13EA /* MessageLabelDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageLabelDelegate.swift; sourceTree = "<group>"; };
@@ -527,6 +529,7 @@
 				3008CB7524F95B6D00E6A617 /* AudioController.swift */,
 				30FDB6F824D1C1000066C48D /* ChatViewController.swift */,
 				30FDB6B524D193DD0066C48D /* Views */,
+				303492942565AABC00A523D0 /* DraftModel.swift */,
 			);
 			path = Chat;
 			sourceTree = "<group>";
@@ -1191,6 +1194,7 @@
 				AEE700252438E0E500D6992E /* ProgressAlertHandler.swift in Sources */,
 				30E348E524F6647D005C93D1 /* FileTextCell.swift in Sources */,
 				306C32322445CDE9001D89F3 /* DcLogger.swift in Sources */,
+				303492952565AABC00A523D0 /* DraftModel.swift in Sources */,
 				78E45E3A21D3CFBC00D4B15E /* SettingsController.swift in Sources */,
 				AE8519EA2272FDCA00ED86F0 /* DeviceContactsHandler.swift in Sources */,
 				78ED838321D5379000243125 /* TextFieldCell.swift in Sources */,

+ 33 - 57
deltachat-ios/Chat/ChatViewController.swift

@@ -24,6 +24,11 @@ class ChatViewController: UITableViewController {
         return dcContext.getChat(chatId: chatId).isGroup
     }()
 
+    lazy var draft: DraftModel = {
+        let draft = DraftModel(chatId: chatId)
+        return draft
+    }()
+
     /// The `InputBarAccessoryView` used as the `inputAccessoryView` in the view controller.
     open var messageInputBar = InputBarAccessoryView()
 
@@ -146,9 +151,9 @@ class ChatViewController: UITableViewController {
 
         if !disableWriting {
             configureMessageInputBar()
-            draftMessage = dcContext.getDraft(chatId: chatId)
-            messageInputBar.inputTextView.text = draftMessage?.text
-            configureQuoteView(draft: draftMessage)
+            draft.parse(draftMsg: dcContext.getDraft(chatId: chatId))
+            messageInputBar.inputTextView.text = draft.draftText
+            configureDraftArea(draft: draft)
         }
 
 
@@ -409,30 +414,18 @@ class ChatViewController: UITableViewController {
         markSeenMessagesInVisibleArea()
     }
 
-    private func configureQuoteView(draft: DcMsg?) {
-        if draftMessage?.quoteText != nil {
-            quotePreview.text = draftMessage?.quoteText
-            if let quoteMessage = draftMessage?.quoteMessage {
-                let contact = quoteMessage.fromContact
-                quotePreview.senderTitle.text = contact.displayName
-                quotePreview.senderTitle.textColor = contact.color
-                quotePreview.citeBar.backgroundColor = contact.color
-                quotePreview.imagePreview.image = quoteMessage.image
-            }
-            messageInputBar.setStackViewItems([quotePreview], forStack: .top, animated: false)
-        }
+    private func configureDraftArea(draft: DraftModel) {
+        quotePreview.configure(draft: draft)
+        // setStackViewItems recalculates the proper messageInputBar height
+        messageInputBar.setStackViewItems([quotePreview], forStack: .top, animated: false)
     }
 
-
-    override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?  {
+    override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
         let action = UIContextualAction(style: .normal, title: nil,
-                                        handler: { (action, view, completionHandler) in
+                                        handler: { (_, _, completionHandler) in
                                             let message = DcMsg(id: self.messageIds[indexPath.row])
-                                            if self.draftMessage == nil {
-                                                self.draftMessage = DcMsg(viewType: DC_MSG_TEXT)
-                                            }
-                                            self.draftMessage?.quoteMessage = message
-                                            self.configureQuoteView(draft: self.draftMessage)
+                                            self.draft.setQuote(quotedMsg: message)
+                                            self.configureDraftArea(draft: self.draft)
                                             completionHandler(true)
                                         })
         if #available(iOS 12.0, *) {
@@ -649,25 +642,7 @@ class ChatViewController: UITableViewController {
     }
 
     @objc private func saveDraft() {
-        if draftMessage == nil && self.messageInputBar.inputTextView.text == nil {
-            return
-        }
-
-        //dismiss draft if it doesn't contain any quotes or text
-        if self.messageInputBar.inputTextView.text == nil && draftMessage?.quoteMessage == nil {
-            draftMessage = nil
-            dcContext.setDraft(chatId: chatId, message: nil)
-            return
-        }
-
-        if draftMessage == nil {
-            draftMessage = DcMsg(viewType: DC_MSG_TEXT)
-        }
-
-        if let draftMessage = draftMessage {
-            draftMessage.text = messageInputBar.inputTextView.text
-            dcContext.setDraft(chatId: chatId, message: draftMessage)
-        }
+        draft.save(context: dcContext)
     }
 
     private func configureMessageInputBar() {
@@ -965,17 +940,18 @@ class ChatViewController: UITableViewController {
         }
     }
 
-    private func sendTextMessage(message: String) {
+    private func sendTextMessage() {
         DispatchQueue.global().async {
-            if self.draftMessage != nil {
-                self.draftMessage?.text = message
-                self.draftMessage?.sendInChat(id: self.chatId)
-                self.draftMessage = nil
-            } else {
-                self.dcContext.sendTextInChat(id: self.chatId, message: message)
+            if let draftText = self.draft.draftText {
+                let message = DcMsg(viewType: DC_MSG_TEXT)
+                message.text = draftText.trimmingCharacters(in: .whitespacesAndNewlines)
+                message.quoteMessage = self.draft.quoteMessage
+                message.sendInChat(id: self.chatId)
+                DispatchQueue.main.async {
+                    self.quotePreview.cancel()
+                }
             }
         }
-        self.quotePreview.cancel()
     }
 
     private func sendImage(_ image: UIImage, message: String? = nil) {
@@ -1234,7 +1210,7 @@ extension ChatViewController: MediaPickerDelegate {
 extension ChatViewController: InputBarAccessoryViewDelegate {
     func inputBar(_ inputBar: InputBarAccessoryView, didPressSendButtonWith text: String) {
         if inputBar.inputTextView.images.isEmpty {
-            self.sendTextMessage(message: text.trimmingCharacters(in: .whitespacesAndNewlines))
+            self.sendTextMessage()
         } else {
             let trimmedText = text.replacingOccurrences(of: "\u{FFFC}", with: "", options: .literal, range: nil)
                 .trimmingCharacters(in: .whitespacesAndNewlines)
@@ -1244,6 +1220,10 @@ extension ChatViewController: InputBarAccessoryViewDelegate {
         inputBar.inputTextView.text = String()
         inputBar.inputTextView.attributedText = nil
     }
+
+    func inputBar(_ inputBar: InputBarAccessoryView, textViewTextDidChangeTo text: String) {
+        draft.draftText = text
+    }
 }
 
 extension ChatViewController: QuotePreviewDelegate {
@@ -1251,11 +1231,7 @@ extension ChatViewController: QuotePreviewDelegate {
         // instead of hiding quote preview we need to remove it from the top view stack
         // setStackViewItems ensures the size of the messagInputBarHeight is
         // calculated correctly
-        messageInputBar.setStackViewItems([], forStack: .top, animated: false)
-        if messageInputBar.inputTextView.text != nil {
-            let message = DcMsg(viewType: DC_MSG_TEXT)
-            message.text = messageInputBar.inputTextView.text
-            self.draftMessage = message
-        }
+        draft.setQuote(quotedMsg: nil)
+        configureDraftArea(draft: draft)
     }
 }

+ 39 - 0
deltachat-ios/Chat/DraftModel.swift

@@ -0,0 +1,39 @@
+import Foundation
+import UIKit
+import DcCore
+
+public class DraftModel {
+    var quoteMessage: DcMsg?
+    var quoteText: String?
+    var draftText: String?
+    let chatId: Int
+
+    public init(chatId: Int) {
+        self.chatId = chatId
+    }
+
+    public func parse(draftMsg: DcMsg?) {
+        draftText = draftMsg?.text
+        quoteText = draftMsg?.quoteText
+        quoteMessage = draftMsg?.quoteMessage
+    }
+
+    public func setQuote(quotedMsg: DcMsg?) {
+        quoteMessage = quotedMsg
+        self.quoteText = quotedMsg?.text
+    }
+
+    func save(context: DcContext) {
+        if draftText == nil && quoteMessage == nil {
+            context.setDraft(chatId: chatId, message: nil)
+            return
+        }
+
+        let draftMessage = DcMsg(viewType: DC_MSG_TEXT)
+        draftMessage.text = draftText
+        if quoteMessage != nil {
+            draftMessage.quoteMessage = quoteMessage
+        }
+        context.setDraft(chatId: chatId, message: draftMessage)
+    }
+}

+ 16 - 20
deltachat-ios/View/QuotePreview.swift

@@ -39,26 +39,6 @@ public class QuotePreview: UIView, InputItem {
         return view
     }()
 
-    public var text: String? {
-        set { quoteView.quote.text = newValue }
-        get { return quoteView.quote.text }
-    }
-
-    public var senderTitle: UILabel {
-        set { quoteView.senderTitle = newValue }
-        get { return quoteView.senderTitle }
-    }
-
-    public var citeBar: UIView {
-        set { quoteView.citeBar = newValue }
-        get { return quoteView.citeBar }
-    }
-
-    public var imagePreview: UIImageView {
-        set { quoteView.imagePreview = newValue }
-        get { return quoteView.imagePreview }
-    }
-
     init() {
         super.init(frame: .zero)
         setupSubviews()
@@ -94,4 +74,20 @@ public class QuotePreview: UIView, InputItem {
         quoteView.prepareForReuse()
         delegate?.onCancel()
     }
+
+    public func configure(draft: DraftModel) {
+        if draft.quoteMessage == nil && draft.quoteText == nil {
+            isHidden = true
+            return
+        }
+        quoteView.quote.text = draft.quoteText ?? draft.quoteMessage?.summary(chars: 80)
+        if let quoteMessage = draft.quoteMessage {
+            let contact = quoteMessage.fromContact
+            quoteView.senderTitle.text = contact.displayName
+            quoteView.senderTitle.textColor = contact.color
+            quoteView.citeBar.backgroundColor = contact.color
+            quoteView.imagePreview.image = quoteMessage.image
+        }
+        isHidden = false
+    }
 }