Contact search results

// FREEBIE
pull/1/head
Michael Kirk 7 years ago
parent 42263b795a
commit f415827da6

@ -34,6 +34,7 @@ class ConversationSearchViewController: UITableViewController {
tableView.register(ConversationSearchResultCell.self, forCellReuseIdentifier: ConversationSearchResultCell.reuseIdentifier)
tableView.register(MessageSearchResultCell.self, forCellReuseIdentifier: MessageSearchResultCell.reuseIdentifier)
tableView.register(ContactSearchResultCell.self, forCellReuseIdentifier: ContactSearchResultCell.reuseIdentifier)
}
// MARK: UITableViewDelegate
@ -102,8 +103,16 @@ class ConversationSearchViewController: UITableViewController {
cell.configure(searchResult: searchResult)
return cell
case .contacts:
// TODO
return UITableViewCell()
guard let cell = tableView.dequeueReusableCell(withIdentifier: ContactSearchResultCell.reuseIdentifier) as? ContactSearchResultCell else {
return UITableViewCell()
}
guard let searchResult = self.searchResultSet.contacts[safe: indexPath.row] else {
return UITableViewCell()
}
cell.configure(searchResult: searchResult)
return cell
case .messages:
guard let cell = tableView.dequeueReusableCell(withIdentifier: MessageSearchResultCell.reuseIdentifier) as? MessageSearchResultCell else {
return UITableViewCell()
@ -209,7 +218,7 @@ class ConversationSearchResultCell: UITableViewCell {
return Environment.current().contactsManager
}
func configure(searchResult: SearchResult) {
func configure(searchResult: ConversationSearchResult) {
self.avatarView.image = OWSAvatarBuilder.buildImage(thread: searchResult.thread.threadRecord, diameter: avatarWidth, contactsManager: self.contactsManager)
self.nameLabel.text = searchResult.thread.name
self.snippetLabel.text = searchResult.snippet
@ -242,7 +251,7 @@ class MessageSearchResultCell: UITableViewCell {
fatalError("init(coder:) has not been implemented")
}
func configure(searchResult: SearchResult) {
func configure(searchResult: ConversationSearchResult) {
self.nameLabel.text = searchResult.thread.name
guard let snippet = searchResult.snippet else {
@ -272,3 +281,49 @@ class MessageSearchResultCell: UITableViewCell {
}
}
}
class ContactSearchResultCell: UITableViewCell {
static let reuseIdentifier = "ContactSearchResultCell"
let nameLabel: UILabel
let snippetLabel: UILabel
let avatarView: AvatarImageView
let avatarWidth: UInt = 40
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
self.nameLabel = UILabel()
self.snippetLabel = UILabel()
self.avatarView = AvatarImageView()
avatarView.autoSetDimensions(to: CGSize(width: CGFloat(avatarWidth), height: CGFloat(avatarWidth)))
super.init(style: style, reuseIdentifier: reuseIdentifier)
nameLabel.font = UIFont.ows_dynamicTypeBody.ows_mediumWeight()
snippetLabel.font = UIFont.ows_dynamicTypeFootnote
let textRows = UIStackView(arrangedSubviews: [nameLabel, snippetLabel])
textRows.axis = .vertical
let columns = UIStackView(arrangedSubviews: [avatarView, textRows])
columns.axis = .horizontal
columns.spacing = 8
contentView.addSubview(columns)
columns.autoPinEdgesToSuperviewMargins()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var contactsManager: OWSContactsManager {
return Environment.current().contactsManager
}
func configure(searchResult: ContactSearchResult) {
let avatarBuilder = OWSContactAvatarBuilder.init(signalId: searchResult.recipientId, diameter: avatarWidth, contactsManager: contactsManager)
self.avatarView.image = avatarBuilder.build()
self.nameLabel.text = self.contactsManager.displayName(forPhoneIdentifier: searchResult.recipientId)
self.snippetLabel.text = searchResult.recipientId
}
}

@ -5,7 +5,7 @@
import Foundation
import SignalServiceKit
public class SearchResult {
public class ConversationSearchResult {
public let thread: ThreadViewModel
public let snippet: String?
@ -15,12 +15,23 @@ public class SearchResult {
}
}
public class ContactSearchResult {
public let signalAccount: SignalAccount
public var recipientId: String {
return signalAccount.recipientId
}
init(signalAccount: SignalAccount) {
self.signalAccount = signalAccount
}
}
public class SearchResultSet {
public let conversations: [SearchResult]
public let contacts: [SearchResult]
public let messages: [SearchResult]
public let conversations: [ConversationSearchResult]
public let contacts: [ContactSearchResult]
public let messages: [ConversationSearchResult]
public init(conversations: [SearchResult], contacts: [SearchResult], messages: [SearchResult]) {
public init(conversations: [ConversationSearchResult], contacts: [ContactSearchResult], messages: [ConversationSearchResult]) {
self.conversations = conversations
self.contacts = contacts
self.messages = messages
@ -44,32 +55,42 @@ public class ConversationSearcher: NSObject {
}
public func results(searchText: String, transaction: YapDatabaseReadTransaction) -> SearchResultSet {
var conversations: [SearchResult] = []
var contacts: [SearchResult] = []
var messages: [SearchResult] = []
var conversations: [ConversationSearchResult] = []
var contacts: [ContactSearchResult] = []
var messages: [ConversationSearchResult] = []
var existingConversationRecipientIds: Set<String> = Set()
self.finder.enumerateObjects(searchText: searchText, transaction: transaction) { (match: Any, snippet: String?) in
if let thread = match as? TSThread {
let threadViewModel = ThreadViewModel(thread: thread, transaction: transaction)
let snippet: String? = thread.lastMessageText(transaction: transaction)
let searchResult = SearchResult(thread: threadViewModel, snippet: snippet)
let searchResult = ConversationSearchResult(thread: threadViewModel, snippet: snippet)
if let contactThread = thread as? TSContactThread {
let recipientId = contactThread.contactIdentifier()
existingConversationRecipientIds.insert(recipientId)
}
conversations.append(searchResult)
} else if let message = match as? TSMessage {
let thread = message.thread(with: transaction)
let threadViewModel = ThreadViewModel(thread: thread, transaction: transaction)
let searchResult = SearchResult(thread: threadViewModel, snippet: snippet)
let searchResult = ConversationSearchResult(thread: threadViewModel, snippet: snippet)
messages.append(searchResult)
} else if let signalAccount = match as? SignalAccount {
// TODO show "other contact" results when there is no existing thread
let searchResult = ContactSearchResult(signalAccount: signalAccount)
contacts.append(searchResult)
} else {
Logger.debug("\(self.logTag) in \(#function) unhandled item: \(match)")
}
}
return SearchResultSet(conversations: conversations, contacts: contacts, messages: messages)
// Only show contacts which were not included in an existing conversation.
let otherContacts: [ContactSearchResult] = contacts.filter { !existingConversationRecipientIds.contains($0.recipientId) }
return SearchResultSet(conversations: conversations, contacts: otherContacts, messages: messages)
}
@objc(filterThreads:withSearchText:)

@ -91,13 +91,13 @@ public class FullTextSearchFinder: NSObject {
private static let recipientIndexer: SearchIndexer<String> = SearchIndexer { (recipientId: String) in
let displayName = contactsManager.displayName(forPhoneIdentifier: recipientId)
let searchableContent = "\(recipientId) \(displayName)"
let searchableContent = "\(recipientId) \(displayName)"
return normalize(text: searchableContent)
}
private static let messageIndexer: SearchIndexer<TSMessage> = SearchIndexer { (message: TSMessage) in
let searchableContent = message.body ?? ""
let searchableContent = message.body ?? ""
return normalize(text: searchableContent)
}
@ -109,6 +109,8 @@ public class FullTextSearchFinder: NSObject {
return self.contactThreadIndexer.index(contactThread)
} else if let message = object as? TSMessage {
return self.messageIndexer.index(message)
} else if let signalAccount = object as? SignalAccount {
return self.recipientIndexer.index(signalAccount.recipientId)
} else {
return nil
}

Loading…
Cancel
Save