show recent search result as default for global search screen

pull/555/head
Ryan Zhao 3 years ago
parent a2db4a8330
commit 85c4b3d745

@ -141,6 +141,7 @@
7B4C75CD26BB92060000AC89 /* DeletedMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4C75CC26BB92060000AC89 /* DeletedMessageView.swift */; }; 7B4C75CD26BB92060000AC89 /* DeletedMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4C75CC26BB92060000AC89 /* DeletedMessageView.swift */; };
7B7CB18B270591630079FF93 /* ShareLogsModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB18A270591630079FF93 /* ShareLogsModal.swift */; }; 7B7CB18B270591630079FF93 /* ShareLogsModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB18A270591630079FF93 /* ShareLogsModal.swift */; };
7BA7F4BB279F9F5800B3A466 /* EmptySearchResultCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA7F4BA279F9F5800B3A466 /* EmptySearchResultCell.swift */; }; 7BA7F4BB279F9F5800B3A466 /* EmptySearchResultCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA7F4BA279F9F5800B3A466 /* EmptySearchResultCell.swift */; };
7BA7F4BD27A216B600B3A466 /* Storage+RecentSearchResults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA7F4BC27A216B600B3A466 /* Storage+RecentSearchResults.swift */; };
7BA9057E27911C5800998B3C /* GlobalSearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA9057D27911C5800998B3C /* GlobalSearchViewController.swift */; }; 7BA9057E27911C5800998B3C /* GlobalSearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA9057D27911C5800998B3C /* GlobalSearchViewController.swift */; };
7BC01A3E241F40AB00BC7C55 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC01A3D241F40AB00BC7C55 /* NotificationServiceExtension.swift */; }; 7BC01A3E241F40AB00BC7C55 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC01A3D241F40AB00BC7C55 /* NotificationServiceExtension.swift */; };
7BC01A42241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7BC01A3B241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 7BC01A42241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7BC01A3B241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@ -1110,6 +1111,7 @@
7B4C75CC26BB92060000AC89 /* DeletedMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedMessageView.swift; sourceTree = "<group>"; }; 7B4C75CC26BB92060000AC89 /* DeletedMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedMessageView.swift; sourceTree = "<group>"; };
7B7CB18A270591630079FF93 /* ShareLogsModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareLogsModal.swift; sourceTree = "<group>"; }; 7B7CB18A270591630079FF93 /* ShareLogsModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareLogsModal.swift; sourceTree = "<group>"; };
7BA7F4BA279F9F5800B3A466 /* EmptySearchResultCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptySearchResultCell.swift; sourceTree = "<group>"; }; 7BA7F4BA279F9F5800B3A466 /* EmptySearchResultCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptySearchResultCell.swift; sourceTree = "<group>"; };
7BA7F4BC27A216B600B3A466 /* Storage+RecentSearchResults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+RecentSearchResults.swift"; sourceTree = "<group>"; };
7BA9057D27911C5800998B3C /* GlobalSearchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchViewController.swift; sourceTree = "<group>"; }; 7BA9057D27911C5800998B3C /* GlobalSearchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalSearchViewController.swift; sourceTree = "<group>"; };
7BC01A3B241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SessionNotificationServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 7BC01A3B241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SessionNotificationServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
7BC01A3D241F40AB00BC7C55 /* NotificationServiceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationServiceExtension.swift; sourceTree = "<group>"; }; 7BC01A3D241F40AB00BC7C55 /* NotificationServiceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationServiceExtension.swift; sourceTree = "<group>"; };
@ -2030,6 +2032,7 @@
children = ( children = (
7BA9057D27911C5800998B3C /* GlobalSearchViewController.swift */, 7BA9057D27911C5800998B3C /* GlobalSearchViewController.swift */,
7BA7F4BA279F9F5800B3A466 /* EmptySearchResultCell.swift */, 7BA7F4BA279F9F5800B3A466 /* EmptySearchResultCell.swift */,
7BA7F4BC27A216B600B3A466 /* Storage+RecentSearchResults.swift */,
); );
path = GlobalSearch; path = GlobalSearch;
sourceTree = "<group>"; sourceTree = "<group>";
@ -4911,6 +4914,7 @@
3427C64320F500E000EEC730 /* OWSMessageTimerView.m in Sources */, 3427C64320F500E000EEC730 /* OWSMessageTimerView.m in Sources */,
B90418E6183E9DD40038554A /* DateUtil.m in Sources */, B90418E6183E9DD40038554A /* DateUtil.m in Sources */,
C33100092558FF6D00070591 /* UserCell.swift in Sources */, C33100092558FF6D00070591 /* UserCell.swift in Sources */,
7BA7F4BD27A216B600B3A466 /* Storage+RecentSearchResults.swift in Sources */,
B8269D2925C7A4B400488AB4 /* InputView.swift in Sources */, B8269D2925C7A4B400488AB4 /* InputView.swift in Sources */,
C374EEE225DA26740073A857 /* LinkPreviewModal.swift in Sources */, C374EEE225DA26740073A857 /* LinkPreviewModal.swift in Sources */,
3496956F21A301A100DCFE74 /* OWSBackupLazyRestore.swift in Sources */, 3496956F21A301A100DCFE74 /* OWSBackupLazyRestore.swift in Sources */,

@ -9,6 +9,7 @@ class GlobalSearchViewController: BaseVC, UITableViewDelegate, UITableViewDataSo
refreshSearchResults() refreshSearchResults()
} }
} }
var recentSearchResults: [String] = []
var searchResultSet: HomeScreenSearchResultSet = HomeScreenSearchResultSet.empty var searchResultSet: HomeScreenSearchResultSet = HomeScreenSearchResultSet.empty
private var lastSearchText: String? private var lastSearchText: String?
var searcher: FullTextSearcher { var searcher: FullTextSearcher {
@ -20,6 +21,7 @@ class GlobalSearchViewController: BaseVC, UITableViewDelegate, UITableViewDataSo
case noResults case noResults
case contacts case contacts
case messages case messages
case recent
} }
// MARK: UI Components // MARK: UI Components
@ -87,6 +89,7 @@ class GlobalSearchViewController: BaseVC, UITableViewDelegate, UITableViewDataSo
} }
private func reloadTableData() { private func reloadTableData() {
recentSearchResults = Array(Storage.shared.getRecentSearchResults().reversed())
tableView.reloadData() tableView.reloadData()
} }
@ -208,23 +211,33 @@ extension GlobalSearchViewController {
let sectionResults = searchResultSet.messages let sectionResults = searchResultSet.messages
guard let searchResult = sectionResults[safe: indexPath.row], let threadId = searchResult.thread.threadRecord.uniqueId, let thread = TSThread.fetch(uniqueId: threadId) else { return } guard let searchResult = sectionResults[safe: indexPath.row], let threadId = searchResult.thread.threadRecord.uniqueId, let thread = TSThread.fetch(uniqueId: threadId) else { return }
show(thread, highlightedMessageID: searchResult.messageId, animated: true) show(thread, highlightedMessageID: searchResult.messageId, animated: true)
case .recent:
guard let threadId = recentSearchResults[safe: indexPath.row], let thread = TSThread.fetch(uniqueId: threadId) else { return }
show(thread, highlightedMessageID: nil, animated: true, isFromRecent: true)
} }
} }
private func show(_ thread: TSThread, highlightedMessageID: String?, animated: Bool) { private func show(_ thread: TSThread, highlightedMessageID: String?, animated: Bool, isFromRecent: Bool = false) {
if let threadId = thread.uniqueId {
Storage.shared.addSearchResults(threadID: threadId)
}
DispatchMainThreadSafe { DispatchMainThreadSafe {
if let presentedVC = self.presentedViewController { if let presentedVC = self.presentedViewController {
presentedVC.dismiss(animated: false, completion: nil) presentedVC.dismiss(animated: false, completion: nil)
} }
let conversationVC = ConversationVC(thread: thread, focusedMessageID: highlightedMessageID) let conversationVC = ConversationVC(thread: thread, focusedMessageID: highlightedMessageID)
self.navigationController?.pushViewController(conversationVC, animated: true) var viewControllers = self.navigationController?.viewControllers
if isFromRecent, let index = viewControllers?.firstIndex(of: self) { viewControllers?.remove(at: index) }
viewControllers?.append(conversationVC)
self.navigationController?.setViewControllers(viewControllers!, animated: true)
} }
} }
// MARK: UITableViewDataSource // MARK: UITableViewDataSource
public func numberOfSections(in tableView: UITableView) -> Int { public func numberOfSections(in tableView: UITableView) -> Int {
return 3 return 4
} }
public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
@ -279,6 +292,12 @@ extension GlobalSearchViewController {
} else { } else {
return nil return nil
} }
case .recent:
if recentSearchResults.count > 0 && searchText.isEmpty {
return NSLocalizedString("SEARCH_SECTION_RECENT", comment: "")
} else {
return nil
}
} }
} }
@ -291,6 +310,8 @@ extension GlobalSearchViewController {
return searchResultSet.conversations.count return searchResultSet.conversations.count
case .messages: case .messages:
return searchResultSet.messages.count return searchResultSet.messages.count
case .recent:
return searchText.isEmpty ? recentSearchResults.count : 0
} }
} }
@ -325,6 +346,15 @@ extension GlobalSearchViewController {
cell.threadViewModel = searchResult?.thread cell.threadViewModel = searchResult?.thread
cell.configure(messageDate: searchResult?.messageDate, snippet: searchResult?.snippet, searchText: searchResultSet.searchText) cell.configure(messageDate: searchResult?.messageDate, snippet: searchResult?.snippet, searchText: searchResultSet.searchText)
return cell return cell
case .recent:
let cell = tableView.dequeueReusableCell(withIdentifier: ConversationCell.reuseIdentifier) as! ConversationCell
cell.isShowingGlobalSearchResult = true
dbReadConnection.read { transaction in
guard let threadId = self.recentSearchResults[safe: indexPath.row], let thread = TSThread.fetch(uniqueId: threadId, transaction: transaction) else { return }
cell.threadViewModel = ThreadViewModel(thread: thread, transaction: transaction)
}
cell.configureForRecent()
return cell
} }
} }
} }

@ -0,0 +1,31 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
extension Storage{
private static let recentSearchResultDatabaseCollection = "RecentSearchResultDatabaseCollection"
private static let recentSearchResultKey = "RecentSearchResult"
public func getRecentSearchResults() -> [String] {
var result: [String]?
Storage.read { transaction in
result = transaction.object(forKey: Storage.recentSearchResultKey, inCollection: Storage.recentSearchResultDatabaseCollection) as? [String]
}
return result ?? []
}
public func clearRecentSearchResults() {
Storage.write { transaction in
transaction.removeObject(forKey: Storage.recentSearchResultKey, inCollection: Storage.recentSearchResultDatabaseCollection)
}
}
public func addSearchResults(threadID: String) {
var recentSearchResults = getRecentSearchResults()
if recentSearchResults.count > 20 { recentSearchResults.remove(at: 0) } // Limit the size of the collection to 20
if let index = recentSearchResults.firstIndex(of: threadID) { recentSearchResults.remove(at: index) }
recentSearchResults.append(threadID)
Storage.write { transaction in
transaction.setObject(recentSearchResults, forKey: Storage.recentSearchResultKey, inCollection: Storage.recentSearchResultDatabaseCollection)
}
}
}

@ -581,3 +581,5 @@
"UNPIN_BUTTON_TEXT" = "Unpin"; "UNPIN_BUTTON_TEXT" = "Unpin";
"SEARCH_SECTION_CONTACTS" = "Contacts and Groups"; "SEARCH_SECTION_CONTACTS" = "Contacts and Groups";
"SEARCH_SECTION_MESSAGES" = "Messages"; "SEARCH_SECTION_MESSAGES" = "Messages";
"SEARCH_SECTION_RECENT" = "Recent";
"RECENT_SEARCH_LAST_MESSAGE_DATETIME" = "last message: %@";

@ -209,6 +209,14 @@ final class ConversationCell : UITableViewCell {
hasMentionView.isHidden = true hasMentionView.isHidden = true
} }
public func configureForRecent() {
displayNameLabel.attributedText = NSMutableAttributedString(string: getDisplayName(), attributes: [.foregroundColor:Colors.text])
bottomLabelStackView.isHidden = false
let snippet = String(format: NSLocalizedString("RECENT_SEARCH_LAST_MESSAGE_DATETIME", comment: ""), DateUtil.formatDate(forDisplay: threadViewModel.lastMessageDate))
snippetLabel.attributedText = NSMutableAttributedString(string: snippet, attributes: [.foregroundColor:Colors.text.withAlphaComponent(Values.lowOpacity)])
timestampLabel.isHidden = true
}
public func configure(messageDate: Date?, snippet: String?, searchText: String) { public func configure(messageDate: Date?, snippet: String?, searchText: String) {
let normalizedSearchText = searchText.lowercased() let normalizedSearchText = searchText.lowercased()
if let messageDate = messageDate, let snippet = snippet { if let messageDate = messageDate, let snippet = snippet {

Loading…
Cancel
Save