Browse Source

Merge pull request #1294 from deltachat/remove_deaddrop_chat

Contact Requests overhaul
bjoern 3 năm trước cách đây
mục cha
commit
8d09bb3c6d

+ 12 - 10
DcCore/DcCore/DC/Wrapper.swift

@@ -196,6 +196,14 @@ public class DcContext {
         return Int(dc_lookup_contact_id_by_addr(contextPointer, addr))
     }
 
+    public func acceptChat(chatId: Int) {
+        dc_accept_chat(contextPointer, UInt32(chatId))
+    }
+
+    public func blockChat(chatId: Int) {
+        dc_block_chat(contextPointer, UInt32(chatId))
+    }
+
     public func getChat(chatId: Int) -> DcChat {
         let chatPointer = dc_get_chat(contextPointer, UInt32(chatId))
         return DcChat(chatPointer: chatPointer)
@@ -215,12 +223,6 @@ public class DcContext {
         }
     }
 
-    @discardableResult
-    public func decideOnContactRequest(_ messageId: Int, _ decision: Int32) -> DcChat {
-        let chatId = dc_decide_on_contact_request(contextPointer, UInt32(messageId), decision)
-        return getChat(chatId: Int(chatId))
-    }
-
     public func getChatlist(flags: Int32, queryString: String?, queryId: Int) -> DcChatlist {
         let start = CFAbsoluteTimeGetCurrent()
         let chatlistPointer = dc_get_chatlist(contextPointer, flags, queryString, UInt32(queryId))
@@ -828,6 +830,10 @@ public class DcChat {
         return Int(dc_chat_is_device_talk(chatPointer)) != 0
     }
 
+    public var isContactRequest: Bool {
+        return Int(dc_chat_is_contact_request(chatPointer)) != 0
+    }
+
     public var canSend: Bool {
         return Int(dc_chat_can_send(chatPointer)) != 0
     }
@@ -938,10 +944,6 @@ public class DcMsg {
         return Int(dc_msg_get_chat_id(messagePointer))
     }
 
-    public var realChatId: Int {
-        return Int(dc_msg_get_real_chat_id(messagePointer))
-    }
-
     public var overrideSenderName: String? {
         guard let cString = dc_msg_get_override_sender_name(messagePointer) else { return nil }
         let swiftString = String(cString: cString)

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

@@ -27,6 +27,7 @@
 		302B84CE2397F6CD001C261F /* URL+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302B84CD2397F6CD001C261F /* URL+Extension.swift */; };
 		302D5450268B6B2300A8B271 /* MessageUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302D544F268B6B2300A8B271 /* MessageUtils.swift */; };
 		302D5454268B84CB00A8B271 /* SettingsVideoChatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302D5453268B84CB00A8B271 /* SettingsVideoChatViewController.swift */; };
+		302D546A2693591700A8B271 /* ChatContactRequestBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302D54692693591700A8B271 /* ChatContactRequestBar.swift */; };
 		302E1BB4252B5AB4008F4264 /* PlayButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302E1BB3252B5AB4008F4264 /* PlayButtonView.swift */; };
 		302E592426A5CF4800DD4F58 /* ConnectivityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302E592326A5CF4800DD4F58 /* ConnectivityViewController.swift */; };
 		30349291256441E200A523D0 /* QuotePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30349290256441E200A523D0 /* QuotePreview.swift */; };
@@ -152,7 +153,6 @@
 		AEE56D762253431E007DC082 /* AccountSetupController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE56D752253431E007DC082 /* AccountSetupController.swift */; };
 		AEE56D80225504DB007DC082 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE56D7F225504DB007DC082 /* Extensions.swift */; };
 		AEE6EC3F2282C59C00EDC689 /* GroupMembersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE6EC3E2282C59C00EDC689 /* GroupMembersViewController.swift */; };
-		AEE6EC412282DF5700EDC689 /* MailboxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE6EC402282DF5700EDC689 /* MailboxViewController.swift */; };
 		AEE6EC482283045D00EDC689 /* EditSettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE6EC472283045D00EDC689 /* EditSettingsController.swift */; };
 		AEE700252438E0E500D6992E /* ProgressAlertHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE700242438E0E500D6992E /* ProgressAlertHandler.swift */; };
 		AEF53BD5248904BF00D309C1 /* GalleryTimeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEF53BD4248904BF00D309C1 /* GalleryTimeLabel.swift */; };
@@ -243,6 +243,7 @@
 		302B84CD2397F6CD001C261F /* URL+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Extension.swift"; sourceTree = "<group>"; };
 		302D544F268B6B2300A8B271 /* MessageUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageUtils.swift; sourceTree = "<group>"; };
 		302D5453268B84CB00A8B271 /* SettingsVideoChatViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsVideoChatViewController.swift; sourceTree = "<group>"; };
+		302D54692693591700A8B271 /* ChatContactRequestBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatContactRequestBar.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; };
 		302E592326A5CF4800DD4F58 /* ConnectivityViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectivityViewController.swift; sourceTree = "<group>"; };
 		30349290256441E200A523D0 /* QuotePreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuotePreview.swift; sourceTree = "<group>"; };
@@ -409,7 +410,6 @@
 		AEE56D752253431E007DC082 /* AccountSetupController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSetupController.swift; sourceTree = "<group>"; tabWidth = 4; };
 		AEE56D7F225504DB007DC082 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
 		AEE6EC3E2282C59C00EDC689 /* GroupMembersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupMembersViewController.swift; sourceTree = "<group>"; };
-		AEE6EC402282DF5700EDC689 /* MailboxViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailboxViewController.swift; sourceTree = "<group>"; };
 		AEE6EC472283045D00EDC689 /* EditSettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditSettingsController.swift; sourceTree = "<group>"; };
 		AEE700242438E0E500D6992E /* ProgressAlertHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressAlertHandler.swift; sourceTree = "<group>"; };
 		AEF53BD4248904BF00D309C1 /* GalleryTimeLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GalleryTimeLabel.swift; sourceTree = "<group>"; };
@@ -603,6 +603,7 @@
 				303492CE2587C2DC00A523D0 /* ChatInputBar.swift */,
 				3067AA4B2666310E00525036 /* ChatInputTextView.swift */,
 				307A82CB25B8D26700748B57 /* ChatEditingBar.swift */,
+				302D54692693591700A8B271 /* ChatContactRequestBar.swift */,
 				302E1BB3252B5AB4008F4264 /* PlayButtonView.swift */,
 				30F8817524DA97DA0023780E /* BackgroundContainer.swift */,
 				3008CB7324F9436C00E6A617 /* AudioPlayerView.swift */,
@@ -790,7 +791,6 @@
 				AE19887423EB264000B4CD5F /* HelpViewController.swift */,
 				304F769425DD237B0094B5E2 /* WebViewViewController.swift */,
 				304F769825DD23D70094B5E2 /* FullMessageViewController.swift */,
-				AEE6EC402282DF5700EDC689 /* MailboxViewController.swift */,
 				785BE16721E247F1003BE98C /* MessageInfoViewController.swift */,
 				7AE0A5481FC42F65005ECB4B /* NewChatViewController.swift */,
 				7A0052C71FBE6CB40048C3BF /* NewContactController.swift */,
@@ -1317,7 +1317,6 @@
 				AEE56D762253431E007DC082 /* AccountSetupController.swift in Sources */,
 				AE8F503524753DFE007FEE0B /* GalleryViewController.swift in Sources */,
 				B2C42570265C325C00B95377 /* MultilineLabelCell.swift in Sources */,
-				AEE6EC412282DF5700EDC689 /* MailboxViewController.swift in Sources */,
 				AEF53BD5248904BF00D309C1 /* GalleryTimeLabel.swift in Sources */,
 				AEE6EC482283045D00EDC689 /* EditSettingsController.swift in Sources */,
 				30653081254358B10093E196 /* QuoteView.swift in Sources */,
@@ -1372,6 +1371,7 @@
 				7A451DB01FB1F84900177250 /* AppCoordinator.swift in Sources */,
 				AE38B31822672DFC00EC37A1 /* ActionCell.swift in Sources */,
 				AE9DAF0D22C1215D004C9591 /* EditContactController.swift in Sources */,
+				302D546A2693591700A8B271 /* ChatContactRequestBar.swift in Sources */,
 				305DDD8725DD97BF00974489 /* DynamicFontButton.swift in Sources */,
 				785BE16821E247F1003BE98C /* MessageInfoViewController.swift in Sources */,
 				AED423D3249F578B00B6B2BB /* AddGroupMembersViewController.swift in Sources */,

+ 0 - 1
deltachat-ios/AppDelegate.swift

@@ -524,7 +524,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         dcContext.setStockTranslation(id: DC_STR_SELF, localizationKey: "self")
         dcContext.setStockTranslation(id: DC_STR_DRAFT, localizationKey: "draft")
         dcContext.setStockTranslation(id: DC_STR_VOICEMESSAGE, localizationKey: "voice_message")
-        dcContext.setStockTranslation(id: DC_STR_DEADDROP, localizationKey: "chat_contact_request")
         dcContext.setStockTranslation(id: DC_STR_IMAGE, localizationKey: "image")
         dcContext.setStockTranslation(id: DC_STR_VIDEO, localizationKey: "video")
         dcContext.setStockTranslation(id: DC_STR_AUDIO, localizationKey: "audio")

+ 43 - 17
deltachat-ios/Chat/ChatViewController.swift

@@ -54,6 +54,13 @@ class ChatViewController: UITableViewController {
         return view
     }()
 
+    public lazy var contactRequestBar: ChatContactRequestBar = {
+        let view = ChatContactRequestBar()
+        view.delegate = self
+        view.translatesAutoresizingMaskIntoConstraints = false
+        return view
+    }()
+
     open override var shouldAutorotate: Bool {
         return false
     }
@@ -239,7 +246,8 @@ class ChatViewController: UITableViewController {
     }
 
     override func loadView() {
-        self.tableView = ChatTableView(messageInputBar: self.disableWriting ? nil : messageInputBar)
+        let inputBar = self.disableWriting && !dcContext.getChat(chatId: chatId).isContactRequest ? nil : messageInputBar
+        self.tableView = ChatTableView(messageInputBar: inputBar)
         self.tableView.delegate = self
         self.tableView.dataSource = self
         self.view = self.tableView
@@ -266,15 +274,20 @@ class ChatViewController: UITableViewController {
         configureEmptyStateView()
 
         if !disableWriting {
-            configureMessageInputBar()
-            draft.parse(draftMsg: dcContext.getDraft(chatId: chatId))
-            messageInputBar.inputTextView.text = draft.text
-            configureDraftArea(draft: draft, animated: false)
-            editingBar.delegate = self
-            tableView.allowsMultipleSelectionDuringEditing = true
+            configureUIForWriting()
+        } else if dcContext.getChat(chatId: chatId).isContactRequest {
+            configureContactRequestBar()
         }
     }
 
+    private func configureUIForWriting() {
+        configureMessageInputBar()
+        draft.parse(draftMsg: dcContext.getDraft(chatId: chatId))
+        messageInputBar.inputTextView.text = draft.text
+        configureDraftArea(draft: draft, animated: false)
+        tableView.allowsMultipleSelectionDuringEditing = true
+    }
+
     private func getTopInsetHeight() -> CGFloat {
         return UIApplication.shared.statusBarFrame.height + (navigationController?.navigationBar.bounds.height ?? 0)
     }
@@ -614,6 +627,14 @@ class ChatViewController: UITableViewController {
         markSeenMessagesInVisibleArea()
     }
 
+    private func configureContactRequestBar() {
+        messageInputBar.setMiddleContentView(contactRequestBar, animated: false)
+        messageInputBar.setLeftStackViewWidthConstant(to: 0, animated: false)
+        messageInputBar.setRightStackViewWidthConstant(to: 0, animated: false)
+        messageInputBar.padding = UIEdgeInsets(top: 6, left: 0, bottom: 6, right: 0)
+        messageInputBar.setStackViewItems([], forStack: .top, animated: false)
+    }
+
     private func configureDraftArea(draft: DraftModel, animated: Bool = true) {
         draftArea.configure(draft: draft)
         if draft.isEditing {
@@ -858,13 +879,7 @@ class ChatViewController: UITableViewController {
     private func showEmptyStateView(_ show: Bool) {
         if show {
             let dcChat = dcContext.getChat(chatId: chatId)
-            if chatId == DC_CHAT_ID_DEADDROP {
-                if dcContext.showEmails != DC_SHOW_EMAILS_ALL {
-                    emptyStateView.text = String.localized("chat_no_contact_requests")
-                } else {
-                    emptyStateView.text = String.localized("chat_no_messages")
-                }
-            } else if dcChat.isGroup {
+            if dcChat.isGroup {
                 if dcChat.isUnpromoted {
                     emptyStateView.text = String.localized("chat_new_group_hint")
                 } else {
@@ -975,9 +990,7 @@ class ChatViewController: UITableViewController {
     }
 
     @objc private func chatProfilePressed() {
-        if chatId != DC_CHAT_ID_DEADDROP {
-            showChatDetail(chatId: chatId)
-        }
+        showChatDetail(chatId: chatId)
     }
 
     @objc private func clipperButtonPressed() {
@@ -1666,6 +1679,19 @@ extension ChatViewController: ChatEditingDelegate {
     }
 }
 
+// MARK: - ChatContactRequestBar
+extension ChatViewController: ChatContactRequestDelegate {
+    func onAcceptPressed() {
+        dcContext.acceptChat(chatId: chatId)
+        configureUIForWriting()
+    }
+
+    func onBlockPressed() {
+        dcContext.blockChat(chatId: chatId)
+        self.navigationController?.popViewController(animated: true)
+    }
+}
+
 // MARK: - QLPreviewControllerDelegate
 extension ChatViewController: QLPreviewControllerDelegate {
     @available(iOS 13.0, *)

+ 91 - 0
deltachat-ios/Chat/Views/ChatContactRequestBar.swift

@@ -0,0 +1,91 @@
+import UIKit
+import InputBarAccessoryView
+import DcCore
+
+public protocol ChatContactRequestDelegate: class {
+    func onAcceptPressed()
+    func onBlockPressed()
+}
+
+public class ChatContactRequestBar: UIView, InputItem {
+    public var inputBarAccessoryView: InputBarAccessoryView?
+    public var parentStackViewPosition: InputStackView.Position?
+    public func textViewDidChangeAction(with textView: InputTextView) {}
+    public func keyboardSwipeGestureAction(with gesture: UISwipeGestureRecognizer) {}
+    public func keyboardEditingEndsAction() {}
+    public func keyboardEditingBeginsAction() {}
+
+    weak var delegate: ChatContactRequestDelegate?
+
+    private lazy var acceptButton: UIButton = {
+        let view = UIButton()
+        view.setTitle(String.localized("accept"), for: .normal)
+        view.setTitleColor(.systemBlue, for: .normal)
+        view.translatesAutoresizingMaskIntoConstraints = false
+        return view
+    }()
+
+    private lazy var blockButton: UIButton = {
+        let view = UIButton()
+        view.setTitle(String.localized("block"), for: .normal)
+        view.setTitleColor(.systemBlue, for: .normal)
+        view.translatesAutoresizingMaskIntoConstraints = false
+        view.isUserInteractionEnabled = true
+        return view
+    }()
+
+    private lazy var mainContentView: UIStackView = {
+        let view = UIStackView(arrangedSubviews: [acceptButton, blockButton])
+        view.axis = .horizontal
+        view.distribution = .fillEqually
+        view.alignment = .center
+        view.translatesAutoresizingMaskIntoConstraints = false
+        return view
+    }()
+
+    convenience init() {
+        self.init(frame: .zero)
+
+    }
+
+    public override init(frame: CGRect) {
+        super.init(frame: frame)
+        self.setupSubviews()
+    }
+
+    required init(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    public func setupSubviews() {
+        addSubview(mainContentView)
+
+        addConstraints([
+            mainContentView.constraintAlignTopTo(self, paddingTop: 4),
+            mainContentView.constraintAlignBottomTo(self, paddingBottom: 4),
+            mainContentView.constraintAlignLeadingTo(self),
+            mainContentView.constraintAlignTrailingTo(self),
+        ])
+
+        backgroundColor = DcColors.chatBackgroundColor
+
+        let acceptGestureListener = UITapGestureRecognizer(target: self, action: #selector(onAcceptPressed))
+        acceptButton.addGestureRecognizer(acceptGestureListener)
+
+        let blockGestureListener = UITapGestureRecognizer(target: self, action: #selector(onBlockPressed))
+        blockButton.addGestureRecognizer(blockGestureListener)
+
+    }
+
+    @objc func onAcceptPressed() {
+        delegate?.onAcceptPressed()
+    }
+
+    @objc func onBlockPressed() {
+        delegate?.onBlockPressed()
+    }
+
+    public override var intrinsicContentSize: CGSize {
+        return CGSize(width: super.intrinsicContentSize.width, height: 44)
+    }
+}

+ 1 - 37
deltachat-ios/Controller/ChatListController.swift

@@ -268,12 +268,6 @@ class ChatListController: UITableViewController {
         let cellData = viewModel.cellDataFor(section: indexPath.section, row: indexPath.row)
 
         switch cellData.type {
-        case .deaddrop:
-            guard let deaddropCell = tableView.dequeueReusableCell(withIdentifier: deadDropCellReuseIdentifier, for: indexPath) as? ContactCell else {
-                break
-            }
-            deaddropCell.updateCell(cellViewModel: cellData)
-            return deaddropCell
         case .chat(let chatData):
             let chatId = chatData.chatId
             if chatId == DC_CHAT_ID_ARCHIVED_LINK {
@@ -305,14 +299,6 @@ class ChatListController: UITableViewController {
     override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
         let cellData = viewModel.cellDataFor(section: indexPath.section, row: indexPath.row)
         switch cellData.type {
-        case .deaddrop(let deaddropData):
-            safe_assert(deaddropData.chatId == DC_CHAT_ID_DEADDROP)
-            if dcContext.showEmails == DC_SHOW_EMAILS_ALL {
-                let deaddropViewController = MailboxViewController(dcContext: dcContext, chatId: Int(DC_CHAT_ID_DEADDROP))
-                navigationController?.pushViewController(deaddropViewController, animated: true)
-            } else {
-                showDeaddropRequestAlert(msgId: deaddropData.msgId)
-            }
         case .chat(let chatData):
             let chatId = chatData.chatId
             if chatId == DC_CHAT_ID_ARCHIVED_LINK {
@@ -339,7 +325,7 @@ class ChatListController: UITableViewController {
             return []
         }
 
-        if chatId==DC_CHAT_ID_ARCHIVED_LINK || chatId==DC_CHAT_ID_DEADDROP {
+        if chatId==DC_CHAT_ID_ARCHIVED_LINK {
             return []
             // returning nil may result in a default delete action,
             // see https://forums.developer.apple.com/thread/115030
@@ -461,28 +447,6 @@ class ChatListController: UITableViewController {
         self.present(alert, animated: true, completion: nil)
     }
 
-    private func showDeaddropRequestAlert(msgId: Int) {
-        let dcMsg = dcContext.getMessage(id: msgId)
-        let (title, startButton, blockButton) = MailboxViewController.deaddropQuestion(context: dcContext, msg: dcMsg)
-        let alert = UIAlertController(title: title, message: nil, preferredStyle: .safeActionSheet)
-        alert.addAction(UIAlertAction(title: startButton, style: .default, handler: { _ in
-            let chat = self.dcContext.decideOnContactRequest(msgId, DC_DECISION_START_CHAT)
-            self.showChat(chatId: chat.id)
-        }))
-        alert.addAction(UIAlertAction(title: String.localized("not_now"), style: .default, handler: { _ in
-            DispatchQueue.global(qos: .userInitiated).async {
-                self.dcContext.decideOnContactRequest(msgId, DC_DECISION_NOT_NOW)
-            }
-        }))
-        alert.addAction(UIAlertAction(title: blockButton, style: .destructive, handler: { _ in
-            DispatchQueue.global(qos: .userInitiated).async {
-                self.dcContext.decideOnContactRequest(msgId, DC_DECISION_BLOCK)
-            }
-        }))
-        alert.addAction(UIAlertAction(title: String.localized("cancel"), style: .cancel))
-        present(alert, animated: true, completion: nil)
-    }
-
     private func askToChatWith(address: String, contactId: Int = 0) {
         var contactId = contactId
         let alert = UIAlertController(title: String.localizedStringWithFormat(String.localized("ask_start_chat_with"), address),

+ 0 - 68
deltachat-ios/Controller/MailboxViewController.swift

@@ -1,68 +0,0 @@
-import UIKit
-import DcCore
-
-class MailboxViewController: ChatViewController {
-
-    override init(dcContext: DcContext, chatId: Int, highlightedMsg: Int? = nil) {
-        super.init(dcContext: dcContext, chatId: chatId)
-        hidesBottomBarWhenPushed = true
-        tableView.allowsSelectionDuringEditing = false
-        showCustomNavBar = false
-    }
-
-    required init?(coder _: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        navigationItem.title = String.localized("menu_deaddrop")
-    }
-
-    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        askToChat(messageId: messageIds[indexPath.row])
-    }
-    
-    override func imageTapped(indexPath: IndexPath) {
-        askToChat(messageId: messageIds[indexPath.row])
-    }
-    override func avatarTapped(indexPath: IndexPath) {
-        askToChat(messageId: messageIds[indexPath.row])
-    }
-    override func textTapped(indexPath: IndexPath) {
-        askToChat(messageId: messageIds[indexPath.row])
-    }
-
-    // function builds the correct question when tapping on a deaddrop message.
-    // returns a tuple (question, startButton, blockButton)
-    public static func deaddropQuestion(context: DcContext, msg: DcMsg) -> (String, String, String) {
-        let chat = context.getChat(chatId: msg.realChatId)
-        if chat.isMailinglist {
-            let question = String.localizedStringWithFormat(String.localized("ask_show_mailing_list"), chat.name)
-            return (question, String.localized("yes"), String.localized("block"))
-        } else {
-            let contact = context.getContact(id: msg.fromContactId)
-            let question = String.localizedStringWithFormat(String.localized("ask_start_chat_with"), contact.nameNAddr)
-            return (question, String.localized("start_chat"), String.localized("menu_block_contact"))
-        }
-    }
-
-    func askToChat(messageId: Int) {
-        if handleUIMenu() { return }
-        let message = dcContext.getMessage(id: messageId)
-        if message.isInfo {
-            return
-        }
-        let (title, startButton, blockButton) = MailboxViewController.deaddropQuestion(context: dcContext, msg: message)
-        let alert = UIAlertController(title: title, message: nil, preferredStyle: .safeActionSheet)
-        alert.addAction(UIAlertAction(title: startButton, style: .default, handler: { _ in
-            let chat = self.dcContext.decideOnContactRequest(messageId, DC_DECISION_START_CHAT)
-            self.showChat(chatId: chat.id)
-        }))
-        alert.addAction(UIAlertAction(title: blockButton, style: .destructive, handler: { _ in
-            self.dcContext.decideOnContactRequest(messageId, DC_DECISION_BLOCK)
-        }))
-        alert.addAction(UIAlertAction(title: String.localized("cancel"), style: .cancel))
-        present(alert, animated: true, completion: nil)
-    }
-}

+ 1 - 16
deltachat-ios/Controller/SettingsController.swift

@@ -13,7 +13,6 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
 
     private enum CellTags: Int {
         case profile = 0
-        case contactRequest = 1
         case showEmails = 2
         case blockedContacts = 3
         case notifications = 4
@@ -53,14 +52,6 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
         return cell
     }()
 
-    private lazy var contactRequestCell: UITableViewCell = {
-        let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
-        cell.tag = CellTags.contactRequest.rawValue
-        cell.textLabel?.text = String.localized("menu_deaddrop")
-        cell.accessoryType = .disclosureIndicator
-        return cell
-    }()
-
     private lazy var showEmailsCell: UITableViewCell = {
         let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
         cell.tag = CellTags.showEmails.rawValue
@@ -220,7 +211,7 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
         let preferencesSection = SectionConfigs(
             headerTitle: String.localized("pref_chats_and_media"),
             footerTitle: String.localized("pref_read_receipts_explain"),
-            cells: [contactRequestCell, showEmailsCell, blockedContactsCell, autodelCell, mediaQualityCell, videoChatInstanceCell, notificationCell, receiptConfirmationCell]
+            cells: [showEmailsCell, blockedContactsCell, autodelCell, mediaQualityCell, videoChatInstanceCell, notificationCell, receiptConfirmationCell]
         )
         let autocryptSection = SectionConfigs(
             headerTitle: String.localized("autocrypt"),
@@ -322,7 +313,6 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
 
         switch cellTag {
         case .profile: showEditSettingsController()
-        case .contactRequest: showContactRequests()
         case .showEmails: showClassicMail()
         case .blockedContacts: showBlockedContacts()
         case .autodel: showAutodelOptions()
@@ -580,11 +570,6 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
         navigationController?.pushViewController(settingsAutodelOverviewController, animated: true)
     }
 
-    private func showContactRequests() {
-        let deaddropViewController = MailboxViewController(dcContext: dcContext, chatId: Int(DC_CHAT_ID_DEADDROP))
-        navigationController?.pushViewController(deaddropViewController, animated: true)
-    }
-
     private func showHelp() {
         navigationController?.pushViewController(HelpViewController(), animated: true)
     }

+ 46 - 49
deltachat-ios/View/ContactCell.swift

@@ -33,7 +33,7 @@ class ContactCell: UITableViewCell {
     }()
 
     lazy var bottomlineStackView: UIStackView = {
-        let stackView = UIStackView(arrangedSubviews: [subtitleLabel, deliveryStatusIndicator, archivedIndicator, unreadMessageCounter])
+        let stackView = UIStackView(arrangedSubviews: [subtitleLabel, deliveryStatusIndicator, archivedIndicator, contactRequest, unreadMessageCounter])
         stackView.axis = .horizontal
         stackView.spacing = 10
         stackView.alignment = .center
@@ -47,7 +47,7 @@ class ContactCell: UITableViewCell {
         return badge
     }()
 
-    let titleLabel: UILabel = {
+    lazy var titleLabel: UILabel = {
         let label = UILabel()
         label.lineBreakMode = .byTruncatingTail
         label.textColor = DcColors.defaultTextColor
@@ -57,7 +57,7 @@ class ContactCell: UITableViewCell {
         return label
     }()
 
-    private let pinnedIndicator: UIImageView = {
+    lazy var pinnedIndicator: UIImageView = {
         let view = UIImageView()
         view.translatesAutoresizingMaskIntoConstraints = false
         view.widthAnchor.constraint(equalToConstant: 16).isActive = true
@@ -68,7 +68,7 @@ class ContactCell: UITableViewCell {
         return view
     }()
 
-    private let mutedIndicator: UIImageView = {
+    lazy var mutedIndicator: UIImageView = {
         let view = UIImageView()
         view.translatesAutoresizingMaskIntoConstraints = false
         view.widthAnchor.constraint(equalToConstant: 16).isActive = true
@@ -79,7 +79,7 @@ class ContactCell: UITableViewCell {
         return view
     }()
 
-    private let timeLabel: UILabel = {
+    lazy var timeLabel: UILabel = {
         let label = UILabel()
         label.font = UIFont.preferredFont(forTextStyle: .subheadline)
         label.adjustsFontForContentSizeCategory = true
@@ -89,14 +89,14 @@ class ContactCell: UITableViewCell {
         return label
     }()
 
-    private let locationStreamingIndicator: UIImageView = {
+    lazy var locationStreamingIndicator: UIImageView = {
         let view = LocationStreamingIndicator(height: 16)
         view.isHidden = true
         view.contentMode = .scaleAspectFit
         return view
     }()
 
-    let subtitleLabel: UILabel = {
+    lazy var subtitleLabel: UILabel = {
         let label = UILabel()
         label.textColor = DcColors.middleGray
         label.lineBreakMode = .byTruncatingTail
@@ -105,33 +105,18 @@ class ContactCell: UITableViewCell {
         return label
     }()
 
-    private let deliveryStatusIndicator: UIImageView = {
+    private lazy var deliveryStatusIndicator: UIImageView = {
         let view = UIImageView()
         view.isHidden = true
         return view
     }()
 
-    private let archivedIndicator: UIView = {
-        let tintColor = UIColor(hexString: "848ba7")
-        let label = UILabel()
-        label.font = label.font.withSize(14)
-        label.text = String.localized("chat_archived_label")
-        label.textColor = tintColor
-        label.setContentHuggingPriority(.defaultHigh, for: NSLayoutConstraint.Axis.horizontal) // needed so label does not expand to available space
-        label.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 2), for: NSLayoutConstraint.Axis.horizontal)
-        let view = UIView()
-        view.layer.borderColor = tintColor.cgColor
-        view.layer.borderWidth = 1
-        view.layer.cornerRadius = 2
-        view.isHidden = true
+    private lazy var archivedIndicator: UIView = {
+        return createTagLabel(tag: String.localized("chat_archived_label"))
+    }()
 
-        label.translatesAutoresizingMaskIntoConstraints = false
-        view.addSubview(label)
-        label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 4).isActive = true
-        label.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
-        label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -4).isActive = true
-        label.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
-        return view
+    private lazy var contactRequest: UIView = {
+        return createTagLabel(tag: String.localized("chat_contact_request"))
     }()
 
     private let unreadMessageCounter: MessageCounter = {
@@ -153,7 +138,28 @@ class ContactCell: UITableViewCell {
         }
     }
 
+    private func createTagLabel(tag: String) -> UIView {
+        let tintColor = UIColor(hexString: "848ba7")
+        let label = UILabel()
+        label.font = label.font.withSize(14)
+        label.text = tag
+        label.textColor = tintColor
+        label.setContentHuggingPriority(.defaultHigh, for: NSLayoutConstraint.Axis.horizontal) // needed so label does not expand to available space
+        label.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 2), for: NSLayoutConstraint.Axis.horizontal)
+        let view = UIView()
+        view.layer.borderColor = tintColor.cgColor
+        view.layer.borderWidth = 1
+        view.layer.cornerRadius = 2
+        view.isHidden = true
 
+        label.translatesAutoresizingMaskIntoConstraints = false
+        view.addSubview(label)
+        label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 4).isActive = true
+        label.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
+        label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -4).isActive = true
+        label.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
+        return view
+    }
     private func configureCompressionPriority() {
         if isLargeText {
             timeLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 1), for: .horizontal)
@@ -224,7 +230,7 @@ class ContactCell: UITableViewCell {
         avatar.setName(name)
     }
 
-    func setStatusIndicators(unreadCount: Int, status: Int, visibility: Int32, isLocationStreaming: Bool, isMuted: Bool) {
+    func setStatusIndicators(unreadCount: Int, status: Int, visibility: Int32, isLocationStreaming: Bool, isMuted: Bool, isContactRequest: Bool) {
         if isLargeText {
             unreadMessageCounter.setCount(unreadCount)
             unreadMessageCounter.isHidden = unreadCount == 0
@@ -232,16 +238,17 @@ class ContactCell: UITableViewCell {
             pinnedIndicator.isHidden = true
             deliveryStatusIndicator.isHidden = true
             archivedIndicator.isHidden = true
+            contactRequest.isHidden = true
             return
         }
 
-        if visibility==DC_CHAT_VISIBILITY_ARCHIVED {
+        if visibility == DC_CHAT_VISIBILITY_ARCHIVED {
             pinnedIndicator.isHidden = true
             unreadMessageCounter.isHidden = true
             deliveryStatusIndicator.isHidden = true
             archivedIndicator.isHidden = false
         } else if unreadCount > 0 {
-            pinnedIndicator.isHidden = !(visibility==DC_CHAT_VISIBILITY_PINNED)
+            pinnedIndicator.isHidden = !(visibility == DC_CHAT_VISIBILITY_PINNED)
             unreadMessageCounter.setCount(unreadCount)
             unreadMessageCounter.isHidden = false
             unreadMessageCounter.backgroundColor = isMuted ? .gray : .red
@@ -261,12 +268,13 @@ class ContactCell: UITableViewCell {
                 deliveryStatusIndicator.image = nil
             }
 
-            pinnedIndicator.isHidden = !(visibility==DC_CHAT_VISIBILITY_PINNED)
+            pinnedIndicator.isHidden = !(visibility == DC_CHAT_VISIBILITY_PINNED)
             unreadMessageCounter.isHidden = true
             deliveryStatusIndicator.isHidden = deliveryStatusIndicator.image == nil ? true : false
             archivedIndicator.isHidden = true
         }
 
+        contactRequest.isHidden = !isContactRequest
         mutedIndicator.isHidden = !isMuted
         locationStreamingIndicator.isHidden = !isLocationStreaming
     }
@@ -293,20 +301,6 @@ class ContactCell: UITableViewCell {
         subtitleLabel.attributedText = cellViewModel.subtitle.boldAt(indexes: cellViewModel.subtitleHighlightIndexes, fontSize: subtitleLabel.font.pointSize)
 
         switch cellViewModel.type {
-        case .deaddrop(let deaddropData):
-            safe_assert(deaddropData.chatId == DC_CHAT_ID_DEADDROP)
-            backgroundColor = DcColors.deaddropBackground
-            let msg = cellViewModel.dcContext.getMessage(id: deaddropData.msgId)
-            let contact = cellViewModel.dcContext.getContact(id: msg.fromContactId)
-            if let img = contact.profileImage {
-                resetBackupImage()
-                setImage(img)
-            } else {
-                setBackupImage(name: contact.nameNAddr, color: contact.color)
-            }
-            setTimeLabel(deaddropData.summary.timestamp)
-            titleLabel.attributedText = cellViewModel.title.boldAt(indexes: cellViewModel.titleHighlightIndexes, fontSize: titleLabel.font.pointSize)
-
         case .chat(let chatData):
             let chat = cellViewModel.dcContext.getChat(chatId: chatData.chatId)
 
@@ -333,7 +327,8 @@ class ContactCell: UITableViewCell {
                                 status: chatData.summary.state,
                                 visibility: chat.visibility,
                                 isLocationStreaming: chat.isSendingLocations,
-                                isMuted: chat.isMuted)
+                                isMuted: chat.isMuted,
+                                isContactRequest: chat.isContactRequest)
 
         case .contact(let contactData):
             let contact = cellViewModel.dcContext.getContact(id: contactData.contactId)
@@ -349,7 +344,8 @@ class ContactCell: UITableViewCell {
                                 status: 0,
                                 visibility: 0,
                                 isLocationStreaming: false,
-                                isMuted: false)
+                                isMuted: false,
+                                isContactRequest: false)
         case .profile:
             let contact = cellViewModel.dcContext.getContact(id: Int(DC_CONTACT_ID_SELF))
             titleLabel.text = cellViewModel.title
@@ -365,7 +361,8 @@ class ContactCell: UITableViewCell {
             status: 0,
             visibility: 0,
             isLocationStreaming: false,
-            isMuted: false)
+            isMuted: false,
+            isContactRequest: false)
         }
 
     }

+ 0 - 7
deltachat-ios/ViewModel/ChatListViewModel.swift

@@ -137,8 +137,6 @@ class ChatListViewModel: NSObject {
     func chatIdFor(section: Int, row: Int) -> Int? {
         let cellData = cellDataFor(section: section, row: row)
         switch cellData.type {
-        case .deaddrop(let data):
-            return data.chatId
         case .chat(let data):
             return data.chatId
         case .contact:
@@ -208,11 +206,6 @@ private extension ChatListViewModel {
         let list: DcChatlist = searchResultChatList ?? chatList
         let chatId = list.getChatId(index: index)
         let summary = list.getSummary(index: index)
-
-        if let msgId = msgIdFor(row: index), chatId == DC_CHAT_ID_DEADDROP {
-            return ChatCellViewModel(dcContext: dcContext, deaddropCellData: DeaddropCellData(chatId: chatId, msgId: msgId, summary: summary))
-        }
-
         let chat = dcContext.getChat(chatId: chatId)
         let unreadMessages = dcContext.getUnreadMessages(chatId: chatId)
 

+ 0 - 16
deltachat-ios/ViewModel/ContactCellViewModel.swift

@@ -13,7 +13,6 @@ protocol AvatarCellViewModel {
 enum CellModel {
     case contact(ContactCellData)
     case chat(ChatCellData)
-    case deaddrop(DeaddropCellData)
     case profile
 }
 
@@ -29,12 +28,6 @@ struct ChatCellData {
     let unreadMessages: Int
 }
 
-struct DeaddropCellData {
-    let chatId: Int
-    let msgId: Int
-    let summary: DcLot
-}
-
 class ContactCellViewModel: AvatarCellViewModel {
 
     private let contact: DcContact
@@ -128,15 +121,6 @@ class ChatCellViewModel: AvatarCellViewModel {
         self.chat = dcContext.getChat(chatId: chatData.chatId)
         self.dcContext = dcContext
     }
-
-    init(dcContext: DcContext, deaddropCellData cellData: DeaddropCellData) {
-        self.type = CellModel.deaddrop(cellData)
-        self.titleHighlightIndexes = []
-        self.subtitleHighlightIndexes = []
-        self.chat = dcContext.getChat(chatId: cellData.chatId)
-        self.summary = cellData.summary
-        self.dcContext = dcContext
-    }
 }
 
 extension ContactCellViewModel {

+ 1 - 0
deltachat-ios/en.lproj/Localizable.strings

@@ -817,3 +817,4 @@
 
 "perm_ios_explain_access_to_camera_denied" = "To take photos, capture videos or use the QR-Code scanner, open the system settings and enable \"Camera\".";
 "open_settings" = "Open Settings";
+"accept" = "Accept";

+ 1 - 0
scripts/untranslated.xml

@@ -12,4 +12,5 @@
     
     <string name="perm_ios_explain_access_to_camera_denied">To take photos, capture videos or use the QR-Code scanner, open the system settings and enable \"Camera\".</string>
     <string name="open_settings">Open Settings</string>
+    <string name="accept">Accept</string>
 </resources>