Prechádzať zdrojové kódy

add new contact action for group creation, use one view controller for adding members in new groups and in existing groups

cyberta 5 rokov pred
rodič
commit
d44c3de7e5

+ 7 - 1
deltachat-ios/Controller/GroupChatDetailViewController.swift

@@ -270,7 +270,13 @@ class GroupChatDetailViewController: UIViewController {
     }
 
     private func showAddGroupMember(chatId: Int) {
-        let groupMemberViewController = AddGroupMembersViewController(chatId: chatId)
+        let groupMemberViewController = NewGroupAddMembersViewController(chatId: chatId)
+        groupMemberViewController.onMembersSelected = { [weak self] (memberIds: Set<Int>) -> Void in
+            guard let self = self else { return }
+            for contactId in memberIds {
+                _ = self.dcContext.addContactToChat(chatId: chatId, contactId: contactId)
+            }
+        }
         navigationController?.pushViewController(groupMemberViewController, animated: true)
     }
 

+ 154 - 13
deltachat-ios/Controller/NewGroupAddMembersViewController.swift

@@ -3,54 +3,195 @@ import DcCore
 
 class NewGroupAddMembersViewController: GroupMembersViewController {
     var onMembersSelected: ((Set<Int>) -> Void)?
-    let isVerifiedGroup: Bool
+    lazy var isVerifiedGroup: Bool = false
+
+    lazy var isNewGroup: Bool = {
+        return chat == nil
+    }()
+
+    private lazy var sections: [AddGroupMemberSections] = {
+        if isVerifiedGroup {
+            return [.memberList]
+        } else {
+            return [.newContact, .memberList]
+        }
+    }()
+
+    enum AddGroupMemberSections {
+        case newContact
+        case memberList
+    }
+
+    private var contactAddedObserver: NSObjectProtocol?
+
+    private lazy var chatMemberIds: [Int] = {
+        if let chat = chat {
+            return chat.contactIds
+        }
+        return []
+    }()
+
+    private lazy var chat: DcChat? = {
+        if let chatId = self.chatId {
+            return dcContext.getChat(chatId: chatId)
+        }
+        return nil
+    }()
+
+    private var chatId: Int?
+
+    private lazy var newContactCell: ActionCell = {
+        let cell = ActionCell()
+        cell.actionColor = SystemColor.blue.uiColor
+        cell.actionTitle = String.localized("menu_new_contact")
+        cell.selectionStyle = .none
+        return cell
+    }()
 
     private lazy var cancelButton: UIBarButtonItem = {
         let button = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelButtonPressed))
         return button
     }()
 
-   lazy var doneButton: UIBarButtonItem = {
-       let button = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonPressed))
-       return button
-   }()
+    lazy var doneButton: UIBarButtonItem = {
+        let button = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonPressed))
+        return button
+    }()
 
+    //add members of new group, no chat object yet
     init(preselected: Set<Int>, isVerified: Bool) {
-        isVerifiedGroup = isVerified
         super.init()
+        isVerifiedGroup = isVerified
+        numberOfSections = sections.count
         selectedContactIds = preselected
     }
 
+    //add members of existing group
+    init(chatId: Int) {
+        self.chatId = chatId
+        super.init()
+        isVerifiedGroup = chat?.isVerified ?? false
+        numberOfSections = sections.count
+        selectedContactIds = []
+    }
+
     required init?(coder _: NSCoder) {
         fatalError("init(coder:) has not been implemented")
     }
 
-    // MARK - lifecycle
+    // MARK: - lifecycle
     override func viewDidLoad() {
         super.viewDidLoad()
         title = String.localized("group_add_members")
         navigationItem.rightBarButtonItem = doneButton
         navigationItem.leftBarButtonItem = cancelButton
-        contactIds = isVerifiedGroup ?
-            dcContext.getContacts(flags: DC_GCL_VERIFIED_ONLY) :
-            dcContext.getContacts(flags: 0)
+        contactIds = loadMemberCandidates()
+
+        let nc = NotificationCenter.default
+        contactAddedObserver = nc.addObserver(
+            forName: dcNotificationContactChanged,
+            object: nil,
+            queue: nil
+        ) { [weak self] notification in
+            guard let self = self else { return }
+            if let ui = notification.userInfo {
+                if let contactId = ui["contact_id"] as? Int {
+                    if contactId == 0 {
+                        return
+                    }
+                    self.contactIds = self.loadMemberCandidates()
+                    if self.contactIds.contains(contactId) {
+                        self.selectedContactIds.insert(contactId)
+
+                        self.tableView.reloadData()
+                    }
+
+                }
+            }
+        }
     }
 
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
     }
 
+    override func viewWillDisappear(_: Bool) {
+        // TODO: - check this for new group context
+        if !isMovingFromParent {
+            // a subview was added to the navigation stack, no action needed
+            return
+        }
+
+        let nc = NotificationCenter.default
+        if let observer = self.contactAddedObserver {
+            nc.removeObserver(observer)
+        }
+    }
+
     @objc func cancelButtonPressed() {
         navigationController?.popViewController(animated: true)
     }
 
     @objc func doneButtonPressed() {
         if let onMembersSelected = onMembersSelected {
-            selectedContactIds.insert(Int(DC_CONTACT_ID_SELF))
+            if isNewGroup {
+                selectedContactIds.insert(Int(DC_CONTACT_ID_SELF))
+            }
             onMembersSelected(selectedContactIds)
-        } else {
-            navigationController?.popViewController(animated: true)
+        }
+        navigationController?.popViewController(animated: true)
+    }
+
+    override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
+        let sectionType = sections[section]
+        switch sectionType {
+        case .newContact:
+            return 1
+        case .memberList:
+            return numberOfRowsForContactList
         }
     }
 
+    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
+        let sectionType = sections[indexPath.section]
+        return sectionType == .memberList ? ContactCell.cellHeight : UITableView.automaticDimension
+    }
+
+    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let sectionType = sections[indexPath.section]
+        switch sectionType {
+        case .newContact:
+            return newContactCell
+        case .memberList:
+            return updateContactCell(for: indexPath)
+        }
+    }
+
+    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        let sectionType = sections[indexPath.section]
+        switch sectionType {
+        case .newContact:
+            tableView.deselectRow(at: indexPath, animated: true)
+            showNewContactController()
+        case .memberList:
+            didSelectContactCell(at: indexPath)
+        }
+    }
+
+    func loadMemberCandidates() -> [Int] {
+        var flags: Int32 = 0
+        if isVerifiedGroup {
+            flags |= DC_GCL_VERIFIED_ONLY
+        }
+        var contactIds = dcContext.getContacts(flags: flags)
+        let memberSet = Set(chatMemberIds)
+        contactIds.removeAll(where: { memberSet.contains($0)})
+        return Array(contactIds)
+    }
+
+    private func showNewContactController() {
+        let newContactController = NewContactController(dcContext: dcContext)
+        newContactController.openChatOnSave = false
+        navigationController?.pushViewController(newContactController, animated: true)
+    }
 }