瀏覽代碼

implement search result highlighting

cyberta 3 年之前
父節點
當前提交
82081ae797

+ 10 - 4
deltachat-ios/Chat/ChatViewController.swift

@@ -670,7 +670,9 @@ class ChatViewController: UITableViewController {
                     msg: message,
                     messageStyle: configureMessageStyle(for: message, at: indexPath),
                     showAvatar: showAvatar,
-                    showName: showName)
+                    showName: showName,
+                    searchText: searchController.searchBar.text,
+                    highlight: !searchMessageIds.isEmpty && message.id == searchMessageIds[searchResultIndex])
 
         return cell
     }
@@ -1802,6 +1804,7 @@ extension ChatViewController: ChatSearchDelegate {
         }
         scrollToMessage(msgId: searchResult[searchResultIndex])
         searchAccessoryBar.updateSearchResult(sum: self.searchMessageIds.count, position: searchResultIndex + 1)
+        self.reloadData()
     }
 
     func onSearchNextPressed() {
@@ -1814,6 +1817,7 @@ extension ChatViewController: ChatSearchDelegate {
         }
         scrollToMessage(msgId: searchResult[searchResultIndex])
         searchAccessoryBar.updateSearchResult(sum: self.searchMessageIds.count, position: searchResultIndex + 1)
+        self.reloadData()
     }
 }
 
@@ -1833,6 +1837,7 @@ extension ChatViewController: UISearchBarDelegate {
                     self.scrollToMessage(msgId: lastId)
                 }
                 self.searchAccessoryBar.updateSearchResult(sum: self.searchMessageIds.count, position: self.searchResultIndex + 1)
+                self.reloadData()
             }
         }
     }
@@ -1848,15 +1853,16 @@ extension ChatViewController: UISearchBarDelegate {
         logger.debug("searchbar: searchBarTextDidEndEditing")
         isSearchActive = false
         configureDraftArea(draft: draft)
-        self.tableView.becomeFirstResponder()
+        tableView.becomeFirstResponder()
     }
 
     func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
         logger.debug("searchbar: searchBarTextDidEndEditing")
         isSearchActive = false
         configureDraftArea(draft: draft)
-        self.searchController.searchBar.isHidden = true
-        self.tableView.becomeFirstResponder()
+        searchController.searchBar.isHidden = true
+        tableView.becomeFirstResponder()
+        reloadData()
     }
 }
 

+ 8 - 2
deltachat-ios/Chat/Views/Cells/AudioMessageCell.swift

@@ -39,7 +39,7 @@ public class AudioMessageCell: BaseMessageCell {
         delegate?.playButtonTapped(cell: self, messageId: messageId)
     }
 
-    override func update(dcContext: DcContext, msg: DcMsg, messageStyle: UIRectCorner, showAvatar: Bool, showName: Bool) {
+    override func update(dcContext: DcContext, msg: DcMsg, messageStyle: UIRectCorner, showAvatar: Bool, showName: Bool, searchText: String? = nil, highlight: Bool) {
         messageId = msg.id
         if let text = msg.text {
             mainContentView.spacing = text.isEmpty ? 0 : 8
@@ -61,7 +61,13 @@ public class AudioMessageCell: BaseMessageCell {
         })
         
 
-        super.update(dcContext: dcContext, msg: msg, messageStyle: messageStyle, showAvatar: showAvatar, showName: showName)
+        super.update(dcContext: dcContext,
+                     msg: msg,
+                     messageStyle: messageStyle,
+                     showAvatar: showAvatar,
+                     showName: showName,
+                     searchText: searchText,
+                     highlight: highlight)
     }
 
     public override func prepareForReuse() {

+ 5 - 1
deltachat-ios/Chat/Views/Cells/BaseMessageCell.swift

@@ -274,7 +274,7 @@ public class BaseMessageCell: UITableViewCell {
     }
 
     // update classes inheriting BaseMessageCell first before calling super.update(...)
-    func update(dcContext: DcContext, msg: DcMsg, messageStyle: UIRectCorner, showAvatar: Bool, showName: Bool) {
+    func update(dcContext: DcContext, msg: DcMsg, messageStyle: UIRectCorner, showAvatar: Bool, showName: Bool, searchText: String?, highlight: Bool) {
         let fromContact = dcContext.getContact(id: msg.fromContactId)
         if msg.isFromCurrentSender {
             topLabel.text = msg.isForwarded ? String.localized("forwarded_message") : nil
@@ -360,6 +360,10 @@ public class BaseMessageCell: UITableViewCell {
             quoteView.isHidden = true
         }
 
+        messageLabel.attributedText = MessageUtils.getFormattedSearchResultMessage(messageText: msg.text,
+                                                                                       searchText: searchText,
+                                                                                       highlight: highlight)
+
         messageLabel.delegate = self
         accessibilityLabel = configureAccessibilityString(message: msg)
     }

+ 8 - 2
deltachat-ios/Chat/Views/Cells/FileTextCell.swift

@@ -29,7 +29,7 @@ class FileTextCell: BaseMessageCell {
         fileView.prepareForReuse()
     }
 
-    override func update(dcContext: DcContext, msg: DcMsg, messageStyle: UIRectCorner, showAvatar: Bool, showName: Bool) {
+    override func update(dcContext: DcContext, msg: DcMsg, messageStyle: UIRectCorner, showAvatar: Bool, showName: Bool, searchText: String? = nil, highlight: Bool) {
         if let text = msg.text, !text.isEmpty {
             messageLabel.text = text
             spacer?.isActive = true
@@ -39,7 +39,13 @@ class FileTextCell: BaseMessageCell {
         
         fileView.configure(message: msg)
         accessibilityLabel = "\(String.localized("document")), \(fileView.configureAccessibilityLabel())"
-        super.update(dcContext: dcContext, msg: msg, messageStyle: messageStyle, showAvatar: showAvatar, showName: showName)
+        super.update(dcContext: dcContext,
+                     msg: msg,
+                     messageStyle: messageStyle,
+                     showAvatar: showAvatar,
+                     showName: showName,
+                     searchText: searchText,
+                     highlight: highlight)
     }
     
 }

+ 8 - 2
deltachat-ios/Chat/Views/Cells/ImageTextCell.swift

@@ -42,7 +42,7 @@ class ImageTextCell: BaseMessageCell {
         contentImageView.addGestureRecognizer(gestureRecognizer)
     }
 
-    override func update(dcContext: DcContext, msg: DcMsg, messageStyle: UIRectCorner, showAvatar: Bool, showName: Bool) {
+    override func update(dcContext: DcContext, msg: DcMsg, messageStyle: UIRectCorner, showAvatar: Bool, showName: Bool, searchText: String? = nil, highlight: Bool) {
         messageLabel.text = msg.text
         let hasEmptyText = msg.text?.isEmpty ?? true
         bottomCompactView = msg.type != DC_MSG_STICKER && !msg.hasHtml && hasEmptyText
@@ -93,7 +93,13 @@ class ImageTextCell: BaseMessageCell {
                 setAspectRatioFor(message: msg, with: placeholderImage, isPlaceholder: true)
             }
         }
-        super.update(dcContext: dcContext, msg: msg, messageStyle: messageStyle, showAvatar: showAvatar, showName: showName)
+        super.update(dcContext: dcContext,
+                     msg: msg,
+                     messageStyle: messageStyle,
+                     showAvatar: showAvatar,
+                     showName: showName,
+                     searchText: searchText,
+                     highlight: highlight)
     }
 
     @objc func onImageTapped() {

+ 9 - 2
deltachat-ios/Chat/Views/Cells/TextMessageCell.swift

@@ -11,9 +11,16 @@ class TextMessageCell: BaseMessageCell {
         messageLabel.paddingTrailing = 12
     }
 
-    override func update(dcContext: DcContext, msg: DcMsg, messageStyle: UIRectCorner, showAvatar: Bool, showName: Bool) {
+    override func update(dcContext: DcContext, msg: DcMsg, messageStyle: UIRectCorner, showAvatar: Bool, showName: Bool, searchText: String?, highlight: Bool) {
         messageLabel.text = msg.text
-        super.update(dcContext: dcContext, msg: msg, messageStyle: messageStyle, showAvatar: showAvatar, showName: showName)
+
+        super.update(dcContext: dcContext,
+                     msg: msg,
+                     messageStyle: messageStyle,
+                     showAvatar: showAvatar,
+                     showName: showName,
+                     searchText: searchText,
+                     highlight: highlight)
     }
 
     override func prepareForReuse() {

+ 21 - 0
deltachat-ios/Helper/MessageUtils.swift

@@ -133,4 +133,25 @@ public class MessageUtils {
         let sendingState = "\(MessageUtils.getSendingStateString(message.state))"
         return "\(date) \(padlock) \(sendingState)"
     }
+
+    public static func getFormattedSearchResultMessage(messageText: String?, searchText: String?, highlight: Bool) -> NSAttributedString? {
+        if let messageText = messageText {
+            let fontAttributes: [NSAttributedString.Key: Any] = [
+                .font: UIFont.preferredFont(for: .body, weight: .regular),
+                .foregroundColor: DcColors.defaultTextColor
+            ]
+            let mutableAttributedString = NSMutableAttributedString(string: messageText, attributes: fontAttributes)
+
+            if let searchText = searchText, messageText.lowercased().contains(searchText.lowercased()) {
+                let range = (messageText.lowercased() as NSString).range(of: searchText.lowercased())
+                mutableAttributedString.addAttribute(.font, value: UIFont.preferredFont(for: .body, weight: .semibold), range: range)
+                if highlight {
+                    mutableAttributedString.addAttribute(.backgroundColor, value: UIColor.systemYellow, range: range)
+                }
+            }
+            return mutableAttributedString
+        }
+
+        return nil
+    }
 }