Parcourir la source

Merge pull request #523 from deltachat/archveDeleteInChatDetail

Fix for #490
nayooti il y a 5 ans
Parent
commit
9ec68df480

+ 34 - 2
deltachat-ios/Controller/ChatListController.swift

@@ -18,6 +18,7 @@ class ChatListController: UIViewController {
     private var msgChangedObserver: Any?
     private var incomingMsgObserver: Any?
     private var viewChatObserver: Any?
+    private var deleteChatObserver: Any?
 
     private var newButton: UIBarButtonItem!
 
@@ -60,6 +61,12 @@ class ChatListController: UIViewController {
                 self.coordinator?.showChat(chatId: chatId)
             }
         }
+
+        deleteChatObserver = nc.addObserver(forName: dcNotificationChatDeletedInChatDetail, object: nil, queue: nil) { notification in
+            if let chatId = notification.userInfo?["chat_id"] as? Int {
+                self.deleteChat(chatId: chatId, animated: true)
+            }
+        }
     }
 
     override func viewDidDisappear(_ animated: Bool) {
@@ -300,10 +307,35 @@ extension ChatListController: UITableViewDataSource, UITableViewDelegate {
             preferredStyle: .safeActionSheet
         )
         alert.addAction(UIAlertAction(title: String.localized("menu_delete_chat"), style: .destructive, handler: { _ in
-            self.dcContext.deleteChat(chatId: chatId)
-            self.getChatList()
+            self.deleteChat(chatId: chatId, animated: true)
         }))
         alert.addAction(UIAlertAction(title: String.localized("cancel"), style: .cancel, handler: nil))
         self.present(alert, animated: true, completion: nil)
     }
+
+    private func deleteChat(chatId: Int, animated: Bool) {
+        self.dcContext.deleteChat(chatId: chatId)
+        if !animated {
+            self.getChatList()
+            return
+        }
+
+        guard let chatList = chatList else {
+            return
+        }
+
+        // find index of chatId
+        let index = Array(0..<chatList.length).filter { chatList.getChatId(index: $0) == chatId }.first
+
+        guard let row = index else {
+            return
+        }
+
+        var gclFlags: Int32 = 0
+        if showArchive {
+            gclFlags |= DC_GCL_ARCHIVED_ONLY
+        }
+        self.chatList = dcContext.getChatlist(flags: gclFlags, queryString: nil, queryId: 0)
+        chatTable.deleteRows(at: [IndexPath(row: row, section: 0)], with: .fade)    
+    }
 }

+ 1 - 1
deltachat-ios/Controller/ChatViewController.swift

@@ -1177,7 +1177,7 @@ extension ChatViewController: MessageCellDelegate {
         if let indexPath = messagesCollectionView.indexPath(for: cell) {
             let message = messageList[indexPath.section]
             let chat = DcChat(id: chatId)
-            coordinator?.showContactDetail(of: message.fromContact.id, in: chat.chatType)
+            coordinator?.showContactDetail(of: message.fromContact.id, in: chat.chatType, chatId: chatId)
         }
     }
 

+ 56 - 6
deltachat-ios/Controller/ContactDetailViewController.swift

@@ -33,6 +33,22 @@ class ContactDetailViewController: UITableViewController {
         return cell
     }()
 
+    private lazy var archiveChatCell: ActionCell = {
+        let cell = ActionCell()
+        cell.actionTitle = viewModel.chatIsArchived ? String.localized("menu_unarchive_chat") :  String.localized("menu_archive_chat")
+        cell.actionColor = SystemColor.blue.uiColor
+        cell.selectionStyle = .none
+        return cell
+    }()
+
+    private lazy var deleteChatCell: ActionCell = {
+        let cell = ActionCell()
+        cell.actionTitle = String.localized("menu_delete_chat")
+        cell.actionColor = UIColor.red
+        cell.selectionStyle = .none
+        return cell
+    }()
+
     init(viewModel: ContactDetailViewModelProtocol) {
         self.viewModel = viewModel
         super.init(style: .grouped)
@@ -76,15 +92,23 @@ class ContactDetailViewController: UITableViewController {
     }
 
     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let row = indexPath.row
         let cellType = viewModel.typeFor(section: indexPath.section)
         switch cellType {
-        case .blockContact:
-            return blockContactCell
+        case .chatActions:
+            if row == 0 {
+                return archiveChatCell
+            } else if row == 1 {
+                return blockContactCell
+            } else {
+                safe_assert(row == 2)
+                return deleteChatCell
+            }
         case .startChat:
             return startChatCell
         case .sharedChats:
             if let cell = tableView.dequeueReusableCell(withIdentifier: ContactCell.reuseIdentifier, for: indexPath) as? ContactCell {
-                viewModel.update(sharedChatCell: cell, row: indexPath.row)
+                viewModel.update(sharedChatCell: cell, row: row)
                 return cell
             }
         }
@@ -94,8 +118,8 @@ class ContactDetailViewController: UITableViewController {
     override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
         let type = viewModel.typeFor(section: indexPath.section)
         switch type {
-        case .blockContact:
-            toggleBlockContact()
+        case .chatActions:
+            handleCellAction(for: indexPath.row)
         case .startChat:
             let contactId = viewModel.contactId
             askToChatWith(contactId: contactId)
@@ -108,7 +132,7 @@ class ContactDetailViewController: UITableViewController {
     override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
         let type = viewModel.typeFor(section: indexPath.section)
         switch type {
-        case .blockContact, .startChat:
+        case .chatActions, .startChat:
             return 44
         case .sharedChats:
             return ContactCell.cellHeight
@@ -120,6 +144,18 @@ class ContactDetailViewController: UITableViewController {
     }
 
     // MARK: -actions
+
+    private func handleCellAction(for index: Int) {
+        if index == 0 {
+            coordinator?.archiveChat()
+        } else if index == 1 {
+            toggleBlockContact()
+        } else {
+            safe_assert(index == 2)
+            showDeleteChatConfirmationAlert()
+        }
+
+    }
     private func askToChatWith(contactId: Int) {
         let dcContact = DcContact(id: contactId)
         let alert = UIAlertController(title: String.localizedStringWithFormat(String.localized("ask_start_chat_with"), dcContact.nameNAddr),
@@ -173,4 +209,18 @@ class ContactDetailViewController: UITableViewController {
     @objc private func editButtonPressed() {
         coordinator?.showEditContact(contactId: viewModel.contactId)
     }
+
+    private func showDeleteChatConfirmationAlert() {
+        let alert = UIAlertController(
+            title: nil,
+            message: String.localized("ask_delete_chat_desktop"),
+            preferredStyle: .safeActionSheet
+        )
+        alert.addAction(UIAlertAction(title: String.localized("menu_delete_chat"), style: .destructive, handler: { _ in
+            self.coordinator?.deleteChat()
+        }))
+        alert.addAction(UIAlertAction(title: String.localized("cancel"), style: .cancel, handler: nil))
+        self.present(alert, animated: true, completion: nil)
+    }
+
 }

+ 37 - 10
deltachat-ios/Coordinator/AppCoordinator.swift

@@ -328,9 +328,9 @@ class NewChatCoordinator: Coordinator {
 
 
     func showContactDetail(contactId: Int) {
-        let viewModel = ContactDetailViewModel(contactId: contactId, startChatOption: true, context: dcContext)
+        let viewModel = ContactDetailViewModel(contactId: contactId, chatId: nil, context: dcContext)
         let contactDetailController = ContactDetailViewController(viewModel: viewModel)
-        let coordinator = ContactDetailCoordinator(dcContext: dcContext, navigationController: navigationController)
+        let coordinator = ContactDetailCoordinator(dcContext: dcContext, chatId: nil, navigationController: navigationController)
         childCoordinators.append(coordinator)
         contactDetailController.coordinator = coordinator
         navigationController.pushViewController(contactDetailController, animated: true)
@@ -379,9 +379,9 @@ class GroupChatDetailCoordinator: Coordinator {
     }
 
     func showContactDetail(of contactId: Int) {
-        let viewModel = ContactDetailViewModel(contactId: contactId, startChatOption: true, context: dcContext)
+        let viewModel = ContactDetailViewModel(contactId: contactId, chatId: nil, context: dcContext)
         let contactDetailController = ContactDetailViewController(viewModel: viewModel)
-        let coordinator = ContactDetailCoordinator(dcContext: dcContext, navigationController: navigationController)
+        let coordinator = ContactDetailCoordinator(dcContext: dcContext, chatId: nil, navigationController: navigationController)
         childCoordinators.append(coordinator)
         contactDetailController.coordinator = coordinator
         navigationController.pushViewController(contactDetailController, animated: true)
@@ -414,9 +414,9 @@ class ChatViewCoordinator: NSObject, Coordinator {
         switch chat.chatType {
         case .SINGLE:
             if let contactId = chat.contactIds.first {
-                let viewModel = ContactDetailViewModel(contactId: contactId, startChatOption: false, context: dcContext)
+                let viewModel = ContactDetailViewModel(contactId: contactId, chatId: chatId, context: dcContext)
                 let contactDetailController = ContactDetailViewController(viewModel: viewModel)
-                let coordinator = ContactDetailCoordinator(dcContext: dcContext, navigationController: navigationController)
+                let coordinator = ContactDetailCoordinator(dcContext: dcContext, chatId: chatId, navigationController: navigationController)
                 childCoordinators.append(coordinator)
                 contactDetailController.coordinator = coordinator
                 navigationController.pushViewController(contactDetailController, animated: true)
@@ -430,7 +430,7 @@ class ChatViewCoordinator: NSObject, Coordinator {
         }
     }
 
-    func showContactDetail(of contactId: Int, in chatOfType: ChatType) {
+    func showContactDetail(of contactId: Int, in chatOfType: ChatType, chatId: Int?) {
         let startChatOption: Bool
         switch chatOfType {
         case .GROUP, .VERYFIEDGROUP:
@@ -438,9 +438,9 @@ class ChatViewCoordinator: NSObject, Coordinator {
         case .SINGLE:
             startChatOption = false
         }
-        let viewModel = ContactDetailViewModel(contactId: contactId, startChatOption: startChatOption, context: dcContext )
+        let viewModel = ContactDetailViewModel(contactId: contactId, chatId: chatId, context: dcContext )
         let contactDetailController = ContactDetailViewController(viewModel: viewModel)
-        let coordinator = ContactDetailCoordinator(dcContext: dcContext, navigationController: navigationController)
+        let coordinator = ContactDetailCoordinator(dcContext: dcContext, chatId: chatId, navigationController: navigationController)
         childCoordinators.append(coordinator)
         contactDetailController.coordinator = coordinator
         navigationController.pushViewController(contactDetailController, animated: true)
@@ -567,12 +567,15 @@ class NewGroupCoordinator: Coordinator {
 }
 
 class ContactDetailCoordinator: Coordinator, ContactDetailCoordinatorProtocol {
+
     var dcContext: DcContext
     let navigationController: UINavigationController
+    let chatId: Int?
 
     private var childCoordinators: [Coordinator] = []
 
-    init(dcContext: DcContext, navigationController: UINavigationController) {
+    init(dcContext: DcContext, chatId: Int?, navigationController: UINavigationController) {
+        self.chatId = chatId
         self.dcContext = dcContext
         self.navigationController = navigationController
     }
@@ -593,6 +596,28 @@ class ContactDetailCoordinator: Coordinator, ContactDetailCoordinatorProtocol {
         editContactController.coordinator = coordinator
         navigationController.pushViewController(editContactController, animated: true)
     }
+
+    func deleteChat() {
+        guard let chatId = chatId else {
+            return
+        }
+
+        func notifyToDeleteChat() {
+            NotificationCenter.default.post(name: dcNotificationChatDeletedInChatDetail, object: nil, userInfo: ["chat_id": chatId])
+        }
+
+        // we want to notify chatList to delete chat AFTER is is visible
+        CATransaction.begin()
+        CATransaction.setAnimationDuration(2)
+        CATransaction.setCompletionBlock(notifyToDeleteChat)
+        self.navigationController.popToRootViewController(animated: true)
+        CATransaction.commit()
+    }
+
+    func archiveChat() {
+        print("archive chat")
+    }
+
 }
 
 class EditGroupCoordinator: Coordinator {
@@ -648,6 +673,8 @@ class EditContactCoordinator: Coordinator, EditContactCoordinatorProtocol {
 protocol ContactDetailCoordinatorProtocol: class {
     func showEditContact(contactId: Int)
     func showChat(chatId: Int)
+    func deleteChat()
+    func archiveChat()
 }
 
 protocol EditContactCoordinatorProtocol: class {

+ 4 - 0
deltachat-ios/DC/Wrapper.swift

@@ -471,6 +471,10 @@ class DcChat {
         return UIColor(netHex: Int(dc_chat_get_color(chatPointer)))
     }
 
+    var isArchived: Bool {
+        return Int(dc_chat_get_archived(chatPointer)) == 1
+    }
+
     var isUnpromoted: Bool {
         return Int(dc_chat_is_unpromoted(chatPointer)) != 0
     }

+ 1 - 0
deltachat-ios/DC/events.swift

@@ -10,6 +10,7 @@ let dcNotificationSecureInviterProgress = Notification.Name(rawValue: "MrEventSe
 let dcNotificationViewChat = Notification.Name(rawValue: "MrEventViewChat")
 let dcNotificationContactChanged = Notification.Name(rawValue: "MrEventContactsChanged")
 let dcNotificationChatModified = Notification.Name(rawValue: "dcNotificationChatModified")
+let dcNotificationChatDeletedInChatDetail = Notification.Name(rawValue: "ChatDeletedInChatDetail")
 
 @_silgen_name("callbackSwift")
 

+ 18 - 6
deltachat-ios/ViewModel/ContactDetailViewModel.swift

@@ -4,6 +4,7 @@ protocol ContactDetailViewModelProtocol {
     var contactId: Int { get }
     var contact: DcContact { get }
     var numberOfSections: Int { get }
+    var chatIsArchived: Bool { get }
     func numberOfRowsInSection(_ : Int) -> Int
     func typeFor(section: Int) -> ContactDetailViewModel.SectionType
     func update(sharedChatCell: ContactCell, row index: Int)
@@ -17,22 +18,24 @@ class ContactDetailViewModel: ContactDetailViewModelProtocol {
     enum SectionType {
         case startChat
         case sharedChats
-        case blockContact
+        case chatActions //  archive chat, block chat, delete chats
     }
 
     var contactId: Int
 
     var contact: DcContact
+    private let chatId: Int?
     private let sharedChats: DcChatlist
     private let startChatOption: Bool
-
     private var sections: [SectionType] = []
 
-    init(contactId: Int, startChatOption: Bool, context: DcContext) {
+    /// if chatId is nil this is a contact detail with 'start chat'-option
+    init(contactId: Int, chatId: Int?, context: DcContext) {
         self.context = context
         self.contactId = contactId
+        self.chatId = chatId
         self.contact = DcContact(id: contactId)
-        self.startChatOption = startChatOption
+        self.startChatOption = chatId == nil
         self.sharedChats = context.getChatlist(flags: 0, queryString: nil, queryId: contactId)
 
         if startChatOption {
@@ -41,13 +44,21 @@ class ContactDetailViewModel: ContactDetailViewModelProtocol {
         if sharedChats.length > 0 {
             sections.append(.sharedChats)
         }
-        sections.append(.blockContact)
+        sections.append(.chatActions)
     }
 
     func typeFor(section: Int) -> ContactDetailViewModel.SectionType {
         return sections[section]
     }
 
+    var chatIsArchived: Bool {
+        guard let chatId = chatId else {
+            safe_fatalError("This is a ContactDetail view with no chat id")
+            return false
+        }
+        return DcChat(id: chatId).isArchived
+    }
+
     var numberOfSections: Int {
         return sections.count
     }
@@ -55,7 +66,8 @@ class ContactDetailViewModel: ContactDetailViewModelProtocol {
     func numberOfRowsInSection(_ section: Int) -> Int {
         switch sections[section] {
         case .sharedChats: return sharedChats.length
-        case .blockContact, .startChat: return 1
+        case .startChat: return 1
+        case .chatActions: return 3
         }
     }