Browse Source

Merge pull request #593 from deltachat/contactListScroll

Fixed contact list scroll bug
cyBerta 5 years ago
parent
commit
8b9c601771

+ 22 - 60
deltachat-ios/Controller/NewChatViewController.swift

@@ -28,21 +28,20 @@ class NewChatViewController: UITableViewController {
     }()
     }()
 
 
     private var contactIds: [Int]
     private var contactIds: [Int]
+    private var filteredContactIds: [Int] = []
 
 
-    // contactWithSearchResults.indexesToHightLight empty by default
-    var contacts: [ContactWithSearchResults] {
-        return contactIds.map { ContactWithSearchResults(contact: DcContact(id: $0), indexesToHighlight: []) }
+    private var searchText: String? {
+        return searchController.searchBar.text
     }
     }
 
 
-    // used when seachbar is active
-    var filteredContacts: [ContactWithSearchResults] = []
-
     // searchBar active?
     // searchBar active?
-    func isFiltering() -> Bool {
-        return !searchBarIsEmpty()
+    var isFiltering: Bool {
+        return !searchBarIsEmpty
     }
     }
 
 
-    // weak var chatDisplayer: ChatDisplayer?
+    private var searchBarIsEmpty: Bool {
+        return searchController.searchBar.text?.isEmpty ?? true
+    }
 
 
     var syncObserver: Any?
     var syncObserver: Any?
     var hud: ProgressHud?
     var hud: ProgressHud?
@@ -140,12 +139,12 @@ class NewChatViewController: UITableViewController {
             return sectionNewRowCount
             return sectionNewRowCount
         } else if section == sectionImportedContacts {
         } else if section == sectionImportedContacts {
             if deviceContactAccessGranted {
             if deviceContactAccessGranted {
-                return isFiltering() ? filteredContacts.count : contacts.count
+                return isFiltering ? filteredContactIds.count : contactIds.count
             } else {
             } else {
                 return 1
                 return 1
             }
             }
         } else {
         } else {
-            return isFiltering() ? filteredContacts.count : contacts.count
+            return isFiltering ? filteredContactIds.count : contactIds.count
         }
         }
     }
     }
 
 
@@ -186,8 +185,8 @@ class NewChatViewController: UITableViewController {
             if deviceContactAccessGranted {
             if deviceContactAccessGranted {
                 let cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath)
                 let cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath)
                 if let contactCell = cell as? ContactCell {
                 if let contactCell = cell as? ContactCell {
-                    let contact: ContactWithSearchResults = contactSearchResultByRow(row)
-                    updateContactCell(cell: contactCell, contactWithHighlight: contact)
+                    let contactCellViewModel = self.contactViewModelBy(row: indexPath.row)
+                    contactCell.updateCell(cellViewModel: contactCellViewModel)
                 }
                 }
                 return cell
                 return cell
             } else {
             } else {
@@ -201,8 +200,8 @@ class NewChatViewController: UITableViewController {
             // section contact list if device contacts are not imported
             // section contact list if device contacts are not imported
             let cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath)
             let cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath)
             if let contactCell = cell as? ContactCell {
             if let contactCell = cell as? ContactCell {
-                let contact: ContactWithSearchResults = contactSearchResultByRow(row)
-                updateContactCell(cell: contactCell, contactWithHighlight: contact)
+                let contactCellViewModel = self.contactViewModelBy(row: indexPath.row)
+                contactCell.updateCell(cellViewModel: contactCellViewModel)
             }
             }
             return cell
             return cell
         }
         }
@@ -265,12 +264,14 @@ class NewChatViewController: UITableViewController {
     }
     }
 
 
     private func contactIdByRow(_ row: Int) -> Int {
     private func contactIdByRow(_ row: Int) -> Int {
-        return isFiltering() ? filteredContacts[row].contact.id : contactIds[row]
+        return isFiltering ? filteredContactIds[row] : contactIds[row]
     }
     }
 
 
-    private func contactSearchResultByRow(_ row: Int) -> ContactWithSearchResults {
-        return isFiltering() ? filteredContacts[row] : contacts[row]
-    }
+    private func contactViewModelBy(row: Int) -> ContactCellViewModel {
+        let id = contactIdByRow(row)
+
+        return ContactCellViewModel.make(contactId: id, searchText: searchText, dcContext: dcContext)
+  }
 
 
     private func askToDeleteContact(contactId: Int, context: DcContext) {
     private func askToDeleteContact(contactId: Int, context: DcContext) {
         let contact = DcContact(id: contactId)
         let contact = DcContact(id: contactId)
@@ -311,7 +312,7 @@ class NewChatViewController: UITableViewController {
     }
     }
 
 
     private func reactivateSearchBarIfNeeded() {
     private func reactivateSearchBarIfNeeded() {
-        if !searchBarIsEmpty() {
+        if !searchBarIsEmpty {
             searchController.isActive = true
             searchController.isActive = true
         }
         }
     }
     }
@@ -329,47 +330,8 @@ class NewChatViewController: UITableViewController {
         }
         }
     }
     }
 
 
-    private func updateContactCell(cell: ContactCell, contactWithHighlight: ContactWithSearchResults) {
-        let contact = contactWithHighlight.contact
-        let displayName = contact.displayName
-
-        let emailLabelFontSize = cell.subtitleLabel.font.pointSize
-        let nameLabelFontSize = cell.titleLabel.font.pointSize
-
-        cell.titleLabel.text = displayName
-        cell.subtitleLabel.text = contact.email
-        cell.avatar.setName(displayName)
-        cell.avatar.setColor(contact.color)
-        if let profileImage = contact.profileImage {
-            cell.avatar.setImage(profileImage)
-        }
-        cell.setVerified(isVerified: contact.isVerified)
-
-        if let emailHighlightedIndexes = contactWithHighlight.indexesToHighlight.filter({ $0.contactDetail == .EMAIL }).first {
-            // gets here when contact is a result of current search -> highlights relevant indexes
-            cell.subtitleLabel.attributedText = contact.email.boldAt(indexes: emailHighlightedIndexes.indexes, fontSize: emailLabelFontSize)
-        } else {
-            cell.subtitleLabel.attributedText = contact.email.boldAt(indexes: [], fontSize: emailLabelFontSize)
-        }
-
-        if let nameHighlightedIndexes = contactWithHighlight.indexesToHighlight.filter({ $0.contactDetail == .NAME }).first {
-            cell.titleLabel.attributedText = displayName.boldAt(indexes: nameHighlightedIndexes.indexes, fontSize: nameLabelFontSize)
-        } else {
-            cell.titleLabel.attributedText = displayName.boldAt(indexes: [], fontSize: nameLabelFontSize)
-        }
-    }
-
-    private func searchBarIsEmpty() -> Bool {
-        return searchController.searchBar.text?.isEmpty ?? true
-    }
-
     private func filterContentForSearchText(_ searchText: String, scope _: String = String.localized("pref_show_emails_all")) {
     private func filterContentForSearchText(_ searchText: String, scope _: String = String.localized("pref_show_emails_all")) {
-        let contactsWithHighlights: [ContactWithSearchResults] = contacts.map { contact in
-            let indexes = contact.contact.containsExact(searchText: searchText)
-            return ContactWithSearchResults(contact: contact.contact, indexesToHighlight: indexes)
-        }
-
-        filteredContacts = contactsWithHighlights.filter { !$0.indexesToHighlight.isEmpty }
+        filteredContactIds = dcContext.getContacts(flags: DC_GCL_ADD_SELF, queryString: searchText)
         tableView.reloadData()
         tableView.reloadData()
         tableView.scrollToTop()
         tableView.scrollToTop()
     }
     }

+ 7 - 4
deltachat-ios/Extensions/String+Extension.swift

@@ -13,15 +13,18 @@ extension String {
         return !trimmingCharacters(in: [" "]).isEmpty
         return !trimmingCharacters(in: [" "]).isEmpty
     }
     }
 
 
-    func containsExact(subSequence: String) -> [Int] {
-        if subSequence.count > count {
+    func containsExact(subSequence: String?) -> [Int] {
+        guard let searchText = subSequence else {
+            return []
+        }
+        if searchText.count > count {
             return []
             return []
         }
         }
 
 
-        if let range = range(of: subSequence, options: .caseInsensitive) {
+        if let range = range(of: searchText, options: .caseInsensitive) {
             let index: Int = distance(from: startIndex, to: range.lowerBound)
             let index: Int = distance(from: startIndex, to: range.lowerBound)
             var indexes: [Int] = []
             var indexes: [Int] = []
-            for i in index..<(index + subSequence.count) {
+            for i in index..<(index + searchText.count) {
                 indexes.append(i)
                 indexes.append(i)
             }
             }
             return indexes
             return indexes

+ 7 - 2
deltachat-ios/View/ContactCell.swift

@@ -281,8 +281,13 @@ class ContactCell: UITableViewCell {
         case .contact(let contactData):
         case .contact(let contactData):
             let contact = DcContact(id: contactData.contactId)
             let contact = DcContact(id: contactData.contactId)
             titleLabel.attributedText = cellViewModel.title.boldAt(indexes: cellViewModel.titleHighlightIndexes, fontSize: titleLabel.font.pointSize)
             titleLabel.attributedText = cellViewModel.title.boldAt(indexes: cellViewModel.titleHighlightIndexes, fontSize: titleLabel.font.pointSize)
-            avatar.setName(cellViewModel.title)
-            avatar.setColor(contact.color)
+            if let profileImage = contact.profileImage {
+                avatar.setImage(profileImage)
+            } else {
+                avatar.setName(cellViewModel.title)
+                avatar.setColor(contact.color)
+            }
+            setVerified(isVerified: contact.isVerified)
             setStatusIndicators(unreadCount: 0, status: 0, visibility: 0, isLocationStreaming: false)
             setStatusIndicators(unreadCount: 0, status: 0, visibility: 0, isLocationStreaming: false)
         }
         }
     }
     }

+ 1 - 18
deltachat-ios/ViewModel/ChatListViewModel.swift

@@ -110,7 +110,7 @@ class ChatListViewModel: NSObject, ChatListViewModelProtocol {
             case .chats:
             case .chats:
                 return makeChatCellViewModel(index: row, searchText: searchText)
                 return makeChatCellViewModel(index: row, searchText: searchText)
             case .contacts:
             case .contacts:
-                return makeContactCellViewModel(contactId: searchResultContactIds[row])
+                return ContactCellViewModel.make(contactId: searchResultContactIds[row], searchText: searchText, dcContext: dcContext)
             case .messages:
             case .messages:
                 return makeMessageCellViewModel(msgId: searchResultMessageIds[row])
                 return makeMessageCellViewModel(msgId: searchResultMessageIds[row])
             }
             }
@@ -223,23 +223,6 @@ private extension ChatListViewModel {
         return viewModel
         return viewModel
     }
     }
 
 
-    func makeContactCellViewModel(contactId: Int) -> AvatarCellViewModel {
-        let contact = DcContact(id: contactId)
-        let nameIndexes = contact.displayName.containsExact(subSequence: searchText)
-        let emailIndexes = contact.email.containsExact(subSequence: searchText)
-        let chatId: Int? = dcContext.getChatIdByContactId(contactId)
-        // contact contains searchText
-        let viewModel = ContactCellViewModel(
-            contactData: ContactCellData(
-                contactId: contact.id,
-                chatId: chatId
-            ),
-            titleHighlightIndexes: nameIndexes,
-            subtitleHighlightIndexes: emailIndexes
-        )
-        return viewModel
-    }
-
     func makeMessageCellViewModel(msgId: Int) -> AvatarCellViewModel {
     func makeMessageCellViewModel(msgId: Int) -> AvatarCellViewModel {
         let msg: DcMsg = DcMsg(id: msgId)
         let msg: DcMsg = DcMsg(id: msgId)
         let chatId: Int = msg.chatId
         let chatId: Int = msg.chatId

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

@@ -100,3 +100,22 @@ class ChatCellViewModel: AvatarCellViewModel {
         self.summary = cellData.summary
         self.summary = cellData.summary
     }
     }
 }
 }
+
+extension ContactCellViewModel {
+    static func make(contactId: Int, searchText: String?, dcContext: DcContext) -> ContactCellViewModel {
+        let contact = DcContact(id: contactId)
+        let nameIndexes = contact.displayName.containsExact(subSequence: searchText)
+        let emailIndexes = contact.email.containsExact(subSequence: searchText)
+        let chatId: Int? = dcContext.getChatIdByContactId(contactId)
+            // contact contains searchText
+        let viewModel = ContactCellViewModel(
+            contactData: ContactCellData(
+                contactId: contact.id,
+                chatId: chatId
+            ),
+            titleHighlightIndexes: nameIndexes,
+            subtitleHighlightIndexes: emailIndexes
+        )
+        return viewModel
+    }
+}