Less confusing class names

-[] Backend
  -[] indexes e5.25
    -[x] wire up results: Contacts / Conversations / Messages actual: 3hr
    -[ ] group thread est: actual:
      -[x] group name actual: e.25
      -[ ] group member name: e.25
      -[ ] group member number: e.25
    -[ ] contact thread e.5
      -[ ] name
      -[ ] number
    -[ ] messages e1
      -[ ] content
-[] Frontend e10.75
  -[x] wire up VC's a.5
  -[x] show search results only when search box has content a.25
  -[] show search results: Contact / Conversation / Messages e2
   -[x] wire up matchs
   -[] style contact cell
   -[] style conversation cell
   -[] style messages cell
  -[] tapping thread search result takes you to conversation e1
  -[] tapping message search result takes you to message e1
  -[] show snippet text for matched message e1
  -[] highlight matched text in thread e3
  -[] go to next search result in thread e2
  -[] No Results page
  -[] Hide search unless pulled down
pull/1/head
Michael Kirk 7 years ago
parent a9e2834d9f
commit f360bcfd35

@ -7,7 +7,7 @@ import Foundation
@objc @objc
class ConversationSearchViewController: UITableViewController { class ConversationSearchViewController: UITableViewController {
var searchResults: ConversationSearchResults = ConversationSearchResults.empty var searchResultSet: SearchResultSet = SearchResultSet.empty
var uiDatabaseConnection: YapDatabaseConnection { var uiDatabaseConnection: YapDatabaseConnection {
// TODO do we want to respond to YapDBModified? Might be hard when there's lots of search results, for only marginal value // TODO do we want to respond to YapDBModified? Might be hard when there's lots of search results, for only marginal value
@ -44,18 +44,18 @@ class ConversationSearchViewController: UITableViewController {
switch searchSection { switch searchSection {
case .conversations: case .conversations:
return searchResults.conversations.count return searchResultSet.conversations.count
case .contacts: case .contacts:
return searchResults.contacts.count return searchResultSet.contacts.count
case .messages: case .messages:
return searchResults.messages.count return searchResultSet.messages.count
} }
} }
class ChatSearchResultCell: UITableViewCell { class ChatSearchResultCell: UITableViewCell {
static let reuseIdentifier = "ChatSearchResultCell" static let reuseIdentifier = "ChatSearchResultCell"
func configure(searchResult: ConversationSearchItem) { func configure(searchResult: SearchResult) {
self.textLabel!.text = searchResult.thread.name self.textLabel!.text = searchResult.thread.name
} }
} }
@ -72,7 +72,7 @@ class ConversationSearchViewController: UITableViewController {
return UITableViewCell() return UITableViewCell()
} }
guard let searchResult = self.searchResults.conversations[safe: indexPath.row] else { guard let searchResult = self.searchResultSet.conversations[safe: indexPath.row] else {
return UITableViewCell() return UITableViewCell()
} }
cell.configure(searchResult: searchResult) cell.configure(searchResult: searchResult)
@ -98,19 +98,19 @@ class ConversationSearchViewController: UITableViewController {
switch searchSection { switch searchSection {
case .conversations: case .conversations:
if searchResults.conversations.count > 0 { if searchResultSet.conversations.count > 0 {
return NSLocalizedString("SEARCH_SECTION_CONVERSATIONS", comment: "section header for search results that match existing conversations (either group or contact conversations)") return NSLocalizedString("SEARCH_SECTION_CONVERSATIONS", comment: "section header for search results that match existing conversations (either group or contact conversations)")
} else { } else {
return nil return nil
} }
case .contacts: case .contacts:
if searchResults.contacts.count > 0 { if searchResultSet.contacts.count > 0 {
return NSLocalizedString("SEARCH_SECTION_CONTACTS", comment: "section header for search results that match a contact who doesn't have an existing conversation") return NSLocalizedString("SEARCH_SECTION_CONTACTS", comment: "section header for search results that match a contact who doesn't have an existing conversation")
} else { } else {
return nil return nil
} }
case .messages: case .messages:
if searchResults.messages.count > 0 { if searchResultSet.messages.count > 0 {
return NSLocalizedString("SEARCH_SECTION_MESSAGES", comment: "section header for search results that match a message in a conversation") return NSLocalizedString("SEARCH_SECTION_MESSAGES", comment: "section header for search results that match a message in a conversation")
} else { } else {
return nil return nil
@ -179,7 +179,7 @@ extension ConversationSearchViewController: UISearchBarDelegate {
public func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { public func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
guard searchText.stripped.count > 0 else { guard searchText.stripped.count > 0 else {
self.searchResults = ConversationSearchResults.empty self.searchResultSet = SearchResultSet.empty
self.view.isHidden = true self.view.isHidden = true
return return
} }
@ -187,7 +187,7 @@ extension ConversationSearchViewController: UISearchBarDelegate {
self.view.isHidden = false self.view.isHidden = false
self.uiDatabaseConnection.read { transaction in self.uiDatabaseConnection.read { transaction in
self.searchResults = self.searcher.results(searchText: searchText, transaction: transaction) self.searchResultSet = self.searcher.results(searchText: searchText, transaction: transaction)
} }
// TODO: more perfomant way to do... // TODO: more perfomant way to do...
self.tableView.reloadData() self.tableView.reloadData()

@ -22,7 +22,7 @@ class ConversationSearcherTest: XCTestCase {
override func setUp() { override func setUp() {
super.setUp() super.setUp()
ConversationFullTextSearchFinder.syncRegisterDatabaseExtension(storage: OWSPrimaryStorage.shared()) FullTextSearchFinder.syncRegisterDatabaseExtension(storage: OWSPrimaryStorage.shared())
} }
// Mark: Tests // Mark: Tests
@ -44,11 +44,11 @@ class ConversationSearcherTest: XCTestCase {
} }
// No Match // No Match
let noMatch = results(searchText: "asdasdasd") let noMatch = resultSet(searchText: "asdasdasd")
XCTAssert(noMatch.conversations.isEmpty) XCTAssert(noMatch.conversations.isEmpty)
// Partial Match // Partial Match
let bookMatch = results(searchText: "Book") let bookMatch = resultSet(searchText: "Book")
XCTAssert(bookMatch.conversations.count == 1) XCTAssert(bookMatch.conversations.count == 1)
if let foundThread: ThreadViewModel = bookMatch.conversations.first?.thread { if let foundThread: ThreadViewModel = bookMatch.conversations.first?.thread {
XCTAssertEqual(bookClubThread, foundThread) XCTAssertEqual(bookClubThread, foundThread)
@ -56,7 +56,7 @@ class ConversationSearcherTest: XCTestCase {
XCTFail("no thread found") XCTFail("no thread found")
} }
let snackMatch = results(searchText: "Snack") let snackMatch = resultSet(searchText: "Snack")
XCTAssert(snackMatch.conversations.count == 1) XCTAssert(snackMatch.conversations.count == 1)
if let foundThread: ThreadViewModel = snackMatch.conversations.first?.thread { if let foundThread: ThreadViewModel = snackMatch.conversations.first?.thread {
XCTAssertEqual(snackClubThread, foundThread) XCTAssertEqual(snackClubThread, foundThread)
@ -65,21 +65,21 @@ class ConversationSearcherTest: XCTestCase {
} }
// Multiple Partial Matches // Multiple Partial Matches
let multipleMatch = results(searchText: "Club") let multipleMatch = resultSet(searchText: "Club")
XCTAssert(multipleMatch.conversations.count == 2) XCTAssert(multipleMatch.conversations.count == 2)
XCTAssert(multipleMatch.conversations.map { $0.thread }.contains(bookClubThread)) XCTAssert(multipleMatch.conversations.map { $0.thread }.contains(bookClubThread))
XCTAssert(multipleMatch.conversations.map { $0.thread }.contains(snackClubThread)) XCTAssert(multipleMatch.conversations.map { $0.thread }.contains(snackClubThread))
// Match Name Exactly // Match Name Exactly
let exactMatch = results(searchText: "Book Club") let exactMatch = resultSet(searchText: "Book Club")
XCTAssert(exactMatch.conversations.count == 1) XCTAssert(exactMatch.conversations.count == 1)
XCTAssertEqual(bookClubThread, exactMatch.conversations.first!.thread) XCTAssertEqual(bookClubThread, exactMatch.conversations.first!.thread)
} }
// Mark: Helpers // Mark: Helpers
private func results(searchText: String) -> ConversationSearchResults { private func resultSet(searchText: String) -> SearchResultSet {
var results: ConversationSearchResults! var results: SearchResultSet!
self.dbConnection.read { transaction in self.dbConnection.read { transaction in
results = self.searcher.results(searchText: searchText, transaction: transaction) results = self.searcher.results(searchText: searchText, transaction: transaction)
} }

@ -6,7 +6,7 @@ import Foundation
import SignalServiceKit import SignalServiceKit
@objc @objc
public class ConversationSearchItem: NSObject { public class SearchResult: NSObject {
@objc @objc
public let thread: ThreadViewModel public let thread: ThreadViewModel
@ -15,19 +15,19 @@ public class ConversationSearchItem: NSObject {
} }
} }
public class ConversationSearchResults { public class SearchResultSet {
public let conversations: [ConversationSearchItem] public let conversations: [SearchResult]
public let contacts: [ConversationSearchItem] public let contacts: [SearchResult]
public let messages: [ConversationSearchItem] public let messages: [SearchResult]
public init(conversations: [ConversationSearchItem], contacts: [ConversationSearchItem], messages: [ConversationSearchItem]) { public init(conversations: [SearchResult], contacts: [SearchResult], messages: [SearchResult]) {
self.conversations = conversations self.conversations = conversations
self.contacts = contacts self.contacts = contacts
self.messages = messages self.messages = messages
} }
public class var empty: ConversationSearchResults { public class var empty: SearchResultSet {
return ConversationSearchResults(conversations: [], contacts: [], messages: []) return SearchResultSet(conversations: [], contacts: [], messages: [])
} }
} }
@ -43,25 +43,25 @@ public class ConversationSearcher: NSObject {
super.init() super.init()
} }
public func results(searchText: String, transaction: YapDatabaseReadTransaction) -> ConversationSearchResults { public func results(searchText: String, transaction: YapDatabaseReadTransaction) -> SearchResultSet {
// TODO limit results, prioritize conversations, then contacts, then messages. // TODO limit results, prioritize conversations, then contacts, then messages.
var conversations: [ConversationSearchItem] = [] var conversations: [SearchResult] = []
var contacts: [ConversationSearchItem] = [] var contacts: [SearchResult] = []
var messages: [ConversationSearchItem] = [] var messages: [SearchResult] = []
self.finder.enumerateObjects(searchText: searchText, transaction: transaction) { (match: Any) in self.finder.enumerateObjects(searchText: searchText, transaction: transaction) { (match: Any) in
if let thread = match as? TSThread { if let thread = match as? TSThread {
let threadViewModel = ThreadViewModel(thread: thread, transaction: transaction) let threadViewModel = ThreadViewModel(thread: thread, transaction: transaction)
let searchItem = ConversationSearchItem(thread: threadViewModel) let searchResult = SearchResult(thread: threadViewModel)
conversations.append(searchItem) conversations.append(searchResult)
} else { } else {
Logger.debug("\(self.logTag) in \(#function) unhandled item: \(match)") Logger.debug("\(self.logTag) in \(#function) unhandled item: \(match)")
} }
} }
return ConversationSearchResults(conversations: conversations, contacts: contacts, messages: messages) return SearchResultSet(conversations: conversations, contacts: contacts, messages: messages)
} }
@objc(filterThreads:withSearchText:) @objc(filterThreads:withSearchText:)

Loading…
Cancel
Save