Răsfoiți Sursa

Merge pull request #1380 from deltachat/instant-grp-qr-join

non-blocking group-joins
bjoern 3 ani în urmă
părinte
comite
ec0b464cd1

+ 0 - 19
DcCore/DcCore/DC/events.swift

@@ -5,7 +5,6 @@ public let dcNotificationChanged = Notification.Name(rawValue: "MrEventMsgsChang
 public let dcNotificationIncoming = Notification.Name(rawValue: "MrEventIncomingMsg")
 public let dcNotificationImexProgress = Notification.Name(rawValue: "dcNotificationImexProgress")
 public let dcNotificationConfigureProgress = Notification.Name(rawValue: "MrEventConfigureProgress")
-public let dcNotificationSecureJoinerProgress = Notification.Name(rawValue: "MrEventSecureJoinerProgress")
 public let dcNotificationSecureInviterProgress = Notification.Name(rawValue: "MrEventSecureInviterProgress")
 public let dcNotificationContactChanged = Notification.Name(rawValue: "MrEventContactsChanged")
 public let dcNotificationChatModified = Notification.Name(rawValue: "dcNotificationChatModified")
@@ -194,24 +193,6 @@ public class DcEventHandler {
                 )
             }
 
-        case DC_EVENT_SECUREJOIN_JOINER_PROGRESS:
-            if dcContext.id != dcAccounts.getSelected().id {
-                return
-            }
-            dcContext.logger?.info("securejoin joiner progress \(data1)")
-            let nc = NotificationCenter.default
-            DispatchQueue.main.async {
-                nc.post(
-                    name: dcNotificationSecureJoinerProgress,
-                    object: nil,
-                    userInfo: [
-                        "contact_id": Int(data1),
-                        "progress": Int(data2),
-                        "error": Int(data2) == 0,
-                        "done": Int(data2) == 1000,
-                    ]
-                )
-            }
         case DC_EVENT_CONTACTS_CHANGED:
             if dcContext.id != dcAccounts.getSelected().id {
                 return

+ 2 - 0
deltachat-ios/AppDelegate.swift

@@ -592,6 +592,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         dcContext.setStockTranslation(id: DC_STR_MESSAGES, localizationKey: "messages")
         dcContext.setStockTranslation(id: DC_STR_BROADCAST_LIST, localizationKey: "broadcast_list")
         dcContext.setStockTranslation(id: DC_STR_PART_OF_TOTAL_USED, localizationKey: "part_of_total_used")
+        dcContext.setStockTranslation(id: DC_STR_SECURE_JOIN_STARTED, localizationKey: "secure_join_started")
+        dcContext.setStockTranslation(id: DC_STR_SECURE_JOIN_REPLIES, localizationKey: "secure_join_replies")
     }
 
     func appIsInForeground() -> Bool {

+ 38 - 12
deltachat-ios/Chat/ChatViewController.swift

@@ -16,6 +16,7 @@ class ChatViewController: UITableViewController {
 
     var msgChangedObserver: NSObjectProtocol?
     var incomingMsgObserver: NSObjectProtocol?
+    var chatModifiedObserver: NSObjectProtocol?
     var ephemeralTimerModifiedObserver: NSObjectProtocol?
     // isDismissing indicates whether the ViewController is/was about to dismissed.
     // The VC can be dismissed by pressing back '<' or by a swipe-to-dismiss gesture.
@@ -220,11 +221,12 @@ class ChatViewController: UITableViewController {
             }
         )
 
+        let dcChat = dcContext.getChat(chatId: chatId)
         let config = ContextMenuProvider()
-        if #available(iOS 13.0, *), !disableWriting {
+        if #available(iOS 13.0, *), dcChat.canSend {
             let mainContextMenu = ContextMenuProvider.ContextMenuItem(submenuitems: [replyItem, forwardItem, infoItem, copyItem, deleteItem])
             config.setMenu([mainContextMenu, selectMoreItem])
-        } else if !disableWriting {
+        } else if dcChat.canSend {
             config.setMenu([forwardItem, infoItem, copyItem, deleteItem, selectMoreItem])
         } else {
             config.setMenu([forwardItem, infoItem, copyItem, deleteItem])
@@ -236,7 +238,6 @@ class ChatViewController: UITableViewController {
     /// The `BasicAudioController` controll the AVAudioPlayer state (play, pause, stop) and update audio cell UI accordingly.
     private lazy var audioController = AudioController(dcContext: dcContext, chatId: chatId, delegate: self)
 
-    private var disableWriting: Bool
     var showCustomNavBar = true
     var highlightedMsg: Int?
 
@@ -253,10 +254,8 @@ class ChatViewController: UITableViewController {
     }()
 
     init(dcContext: DcContext, chatId: Int, highlightedMsg: Int? = nil) {
-        let dcChat = dcContext.getChat(chatId: chatId)
         self.dcContext = dcContext
         self.chatId = chatId
-        self.disableWriting = !dcChat.canSend
         self.highlightedMsg = highlightedMsg
         super.init(nibName: nil, bundle: nil)
         hidesBottomBarWhenPushed = true
@@ -267,8 +266,7 @@ class ChatViewController: UITableViewController {
     }
 
     override func loadView() {
-        let inputBar = self.disableWriting && !dcContext.getChat(chatId: chatId).isContactRequest ? nil : messageInputBar
-        self.tableView = ChatTableView(messageInputBar: inputBar)
+        self.tableView = ChatTableView(messageInputBar: messageInputBar)
         self.tableView.delegate = self
         self.tableView.dataSource = self
         self.view = self.tableView
@@ -296,10 +294,13 @@ class ChatViewController: UITableViewController {
         }
         configureEmptyStateView()
 
-        if !disableWriting {
+        let dcChat = dcContext.getChat(chatId: chatId)
+        if dcChat.canSend {
             configureUIForWriting()
-        } else if dcContext.getChat(chatId: chatId).isContactRequest {
+        } else if dcChat.isContactRequest {
             configureContactRequestBar()
+        } else {
+            messageInputBar.isHidden = true
         }
         loadMessages()
     }
@@ -473,7 +474,8 @@ class ChatViewController: UITableViewController {
         ) { [weak self] notification in
             guard let self = self else { return }
             if let ui = notification.userInfo {
-                if self.disableWriting {
+                let dcChat = self.dcContext.getChat(chatId: self.chatId)
+                if !dcChat.canSend {
                     // always refresh, as we can't check currently
                     self.refreshMessages()
                 } else if let id = ui["message_id"] as? Int {
@@ -485,7 +487,7 @@ class ChatViewController: UITableViewController {
                     }
                 }
                 if self.showCustomNavBar {
-                    self.updateTitle(chat: self.dcContext.getChat(chatId: self.chatId))
+                    self.updateTitle(chat: dcChat)
                 }
             }
         }
@@ -507,6 +509,26 @@ class ChatViewController: UITableViewController {
             }
         }
 
+        chatModifiedObserver = nc.addObserver(
+            forName: dcNotificationChatModified,
+            object: nil, queue: OperationQueue.main
+        ) { [weak self] notification in
+            guard let self = self else { return }
+            if let ui = notification.userInfo, self.chatId == ui["chat_id"] as? Int {
+                let dcChat = self.dcContext.getChat(chatId: self.chatId)
+                if dcChat.canSend {
+                    if self.messageInputBar.isHidden {
+                        self.configureUIForWriting()
+                        self.messageInputBar.isHidden = false
+                    }
+                } else if !dcChat.isContactRequest {
+                    if !self.messageInputBar.isHidden {
+                        self.messageInputBar.isHidden = true
+                    }
+                }
+            }
+        }
+
         ephemeralTimerModifiedObserver = nc.addObserver(
             forName: dcEphemeralTimerModified,
             object: nil, queue: OperationQueue.main
@@ -534,6 +556,9 @@ class ChatViewController: UITableViewController {
         if let incomingMsgObserver = self.incomingMsgObserver {
             nc.removeObserver(incomingMsgObserver)
         }
+        if let chatModifiedObserver = self.chatModifiedObserver {
+            nc.removeObserver(chatModifiedObserver)
+        }
         if let ephemeralTimerModifiedObserver = self.ephemeralTimerModifiedObserver {
             nc.removeObserver(ephemeralTimerModifiedObserver)
         }
@@ -734,7 +759,8 @@ class ChatViewController: UITableViewController {
 
     override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
         let message = dcContext.getMessage(id: messageIds[indexPath.row])
-        if disableWriting || message.isInfo || message.type == DC_MSG_VIDEOCHAT_INVITATION {
+        let dcChat = dcContext.getChat(chatId: chatId)
+        if !dcChat.canSend || message.isInfo || message.type == DC_MSG_VIDEOCHAT_INVITATION {
             return nil
         }
 

+ 3 - 5
deltachat-ios/Chat/Views/ChatTableView.swift

@@ -3,18 +3,17 @@ import InputBarAccessoryView
 
 class ChatTableView: UITableView {
 
-    var messageInputBar: InputBarAccessoryView?
+    var messageInputBar: InputBarAccessoryView
+    
     override var inputAccessoryView: UIView? {
         return messageInputBar
     }
 
-
     override var canBecomeFirstResponder: Bool {
         return true
     }
 
-
-    public init(messageInputBar: InputBarAccessoryView?) {
+    public init(messageInputBar: InputBarAccessoryView) {
         self.messageInputBar = messageInputBar
         super.init(frame: .zero, style: .plain)
     }
@@ -22,5 +21,4 @@ class ChatTableView: UITableView {
     required init?(coder: NSCoder) {
         fatalError("init(coder:) has not been implemented")
     }
-
 }

+ 40 - 23
deltachat-ios/Controller/GroupChatDetailViewController.swift

@@ -25,21 +25,17 @@ class GroupChatDetailViewController: UIViewController {
         case deleteChat
     }
 
-    private let chatOptions: [ChatOption]
-    private let chatActions: [ChatAction]
+    private var chatOptions: [ChatOption]
+    private var chatActions: [ChatAction]
 
     private let membersRowAddMembers = 0
     private let membersRowQrInvite = 1
-    private let memberManagementRows: Int
+    private var memberManagementRows: Int
 
     private let dcContext: DcContext
 
     private let sections: [ProfileSections]
 
-    private lazy var canEdit: Bool = {
-        return chat.isMailinglist || chat.canSend
-    }()
-
     private var chatId: Int
     private var chat: DcChat {
         return dcContext.getChat(chatId: chatId)
@@ -174,20 +170,14 @@ class GroupChatDetailViewController: UIViewController {
         self.chatId = chatId
 
         let chat = dcContext.getChat(chatId: chatId)
+        self.chatActions = []
+        self.chatOptions = []
+        self.memberManagementRows = 0
         if chat.isMailinglist {
-            self.chatOptions = [.gallery, .documents, .search, .muteChat]
-            self.chatActions = [.archiveChat, .deleteChat]
-            self.memberManagementRows = 2
             self.sections = [.chatOptions, .chatActions]
         } else if chat.isBroadcast {
-            self.chatOptions = [.gallery, .documents]
-            self.chatActions = [.archiveChat, .deleteChat]
-            self.memberManagementRows = 1
             self.sections = [.chatOptions, .members, .chatActions]
         } else {
-            self.chatOptions = [.gallery, .documents, .search, .ephemeralMessages, .muteChat]
-            self.chatActions = [.archiveChat, .leaveGroup, .deleteChat]
-            self.memberManagementRows = 2
             self.sections = [.chatOptions, .members, .chatActions]
         }
 
@@ -225,10 +215,11 @@ class GroupChatDetailViewController: UIViewController {
 
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
-        // update chat object, maybe chat name was edited
+
         updateGroupMembers()
-        tableView.reloadData() // to display updates
-        editBarButtonItem.isEnabled = canEdit
+        updateOptions()
+        tableView.reloadData()
+
         setupObservers()
         updateHeader()
         updateMediaCellValues()
@@ -279,6 +270,8 @@ class GroupChatDetailViewController: UIViewController {
                self.chatId == ui["chat_id"] as? Int {
                 self.updateHeader()
                 self.updateGroupMembers()
+                self.updateOptions()
+                self.tableView.reloadData()
             }
         }
     }
@@ -299,7 +292,28 @@ class GroupChatDetailViewController: UIViewController {
     // MARK: - update
     private func updateGroupMembers() {
         groupMemberIds = chat.getContactIds(dcContext)
-        tableView.reloadData()
+    }
+
+    private func updateOptions() {
+        self.editBarButtonItem.isEnabled = chat.isMailinglist || chat.canSend
+
+        if chat.isMailinglist {
+            self.chatOptions = [.gallery, .documents, .search, .muteChat]
+            self.memberManagementRows = 0
+            self.chatActions = [.archiveChat, .deleteChat]
+        } else if chat.isBroadcast {
+            self.chatOptions = [.gallery, .documents, .search]
+            self.memberManagementRows = 1
+            self.chatActions = [.archiveChat, .deleteChat]
+        } else if chat.canSend {
+            self.chatOptions = [.gallery, .documents, .search, .ephemeralMessages, .muteChat]
+            self.memberManagementRows = 2
+            self.chatActions = [.archiveChat, .leaveGroup, .deleteChat]
+        } else {
+            self.chatOptions = [.gallery, .documents, .search, .muteChat]
+            self.memberManagementRows = 0
+            self.chatActions = [.archiveChat, .deleteChat]
+        }
     }
 
     private func updateHeader() {
@@ -340,7 +354,12 @@ class GroupChatDetailViewController: UIViewController {
      }
 
     private func getGroupMemberIdFor(_ row: Int) -> Int {
-        return groupMemberIds[row - memberManagementRows]
+        let index = row - memberManagementRows
+        if index >= 0 && index < groupMemberIds.count {
+            return groupMemberIds[index]
+        } else {
+            return 0
+        }
     }
 
     private func isMemberManagementRow(row: Int) -> Bool {
@@ -686,8 +705,6 @@ extension GroupChatDetailViewController {
         let alert = UIAlertController(title: String.localized("ask_leave_group"), message: nil, preferredStyle: .safeActionSheet)
         alert.addAction(UIAlertAction(title: String.localized("menu_leave_group"), style: .destructive, handler: { _ in
             _ = self.dcContext.removeContactFromChat(chatId: self.chat.id, contactId: Int(DC_CONTACT_ID_SELF))
-            self.editBarButtonItem.isEnabled = false
-            self.updateGroupMembers()
         }))
         alert.addAction(UIAlertAction(title: String.localized("cancel"), style: .cancel, handler: nil))
         present(alert, animated: true, completion: nil)

+ 7 - 47
deltachat-ios/Controller/QrPageController.swift

@@ -1,9 +1,8 @@
 import UIKit
 import DcCore
 
-class QrPageController: UIPageViewController, ProgressAlertHandler {
+class QrPageController: UIPageViewController {
     private let dcContext: DcContext
-    weak var progressAlert: UIAlertController?
     var progressObserver: NSObjectProtocol?
     var qrCodeReaderController: QrCodeReaderController?
 
@@ -288,24 +287,12 @@ extension QrPageController: QrCodeReaderDelegate {
                                       preferredStyle: .alert)
         alert.addAction(UIAlertAction(title: String.localized("cancel"), style: .default, handler: nil))
         alert.addAction(UIAlertAction(title: String.localized("ok"), style: .default, handler: { _ in
-            alert.dismiss(animated: true, completion: nil)
-            self.showProgressAlert(title: String.localized("one_moment")+"\n\n", dcContext: self.dcContext)
-            // execute blocking secure join in background
-            DispatchQueue.global(qos: .background).async {
-                self.addSecureJoinProgressListener()
-                self.dcContext.lastErrorString = nil
-                let chatId = self.dcContext.joinSecurejoin(qrCode: code)
-                let errorString = self.dcContext.lastErrorString
-                self.removeSecureJoinProgressListener()
-
-                DispatchQueue.main.async {
-                    self.progressAlert?.dismiss(animated: true, completion: nil)
-                    if chatId != 0 {
-                        self.showChat(chatId: chatId)
-                    } else if errorString != nil {
-                        self.showErrorAlert(error: errorString!)
-                    }
-                }
+            self.dcContext.lastErrorString = nil
+            let chatId = self.dcContext.joinSecurejoin(qrCode: code)
+            if chatId != 0 {
+                self.showChat(chatId: chatId)
+            } else {
+                self.showErrorAlert(error: self.dcContext.lastErrorString ?? "ErrJoinNoString")
             }
         }))
         present(alert, animated: true, completion: nil)
@@ -317,31 +304,4 @@ extension QrPageController: QrCodeReaderDelegate {
             alert.dismiss(animated: true, completion: nil)
         }))
     }
-
-    private func addSecureJoinProgressListener() {
-        let nc = NotificationCenter.default
-        progressObserver = nc.addObserver(
-            forName: dcNotificationSecureJoinerProgress,
-            object: nil,
-            queue: nil
-        ) { [weak self] notification in
-            guard let self = self else { return }
-            if let ui = notification.userInfo,
-                ui["progress"] as? Int == 400,
-                let contactId = ui["contact_id"] as? Int {
-                self.progressAlert?.message = String.localizedStringWithFormat(
-                    String.localized("qrscan_x_verified_introduce_myself"),
-                    self.dcContext.getContact(id: contactId).nameNAddr
-                )
-            }
-        }
-    }
-
-    private func removeSecureJoinProgressListener() {
-        let nc = NotificationCenter.default
-        if let observer = self.progressObserver {
-            nc.removeObserver(observer)
-        }
-    }
-
 }