Add global search filtering

This commit is contained in:
Ilya Laktyushin 2020-08-21 15:18:34 +03:00
parent 9b342df78d
commit edd2db706b
5 changed files with 43 additions and 26 deletions

View File

@ -762,7 +762,30 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
)
)
let location: SearchMessagesLocation
location = .general(tags: nil)
let messageTags: MessageTags?
if query.hasPrefix("%media ") {
messageTags = .photoOrVideo
} else if query.hasPrefix("%photo ") {
messageTags = .photo
} else if query.hasPrefix("%video ") {
messageTags = .video
} else if query.hasPrefix("%file ") {
messageTags = .file
} else if query.hasPrefix("%music ") {
messageTags = .music
} else if query.hasPrefix("%link ") {
messageTags = .webPage
} else if query.hasPrefix("%gif ") {
messageTags = .gif
} else {
messageTags = nil
}
location = .general(tags: messageTags)
var finalQuery = query
if let _ = messageTags, let index = finalQuery.firstIndex(of: " ") {
finalQuery = String(finalQuery.suffix(from: finalQuery.index(after: index)))
}
updateSearchContext { _ in
return (nil, true)
@ -771,22 +794,22 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
if filter.contains(.doNotSearchMessages) {
foundRemoteMessages = .single((([], [:], 0), false))
} else {
if !query.isEmpty {
if !finalQuery.isEmpty {
addAppLogEvent(postbox: context.account.postbox, time: Date().timeIntervalSince1970, type: "search_global_query", peerId: nil, data: .dictionary([:]))
}
let searchSignal = searchMessages(account: context.account, location: location, query: query, state: nil, limit: 50)
let searchSignal = searchMessages(account: context.account, location: location, query: finalQuery, state: nil, limit: 50)
|> map { result, updatedState -> ChatListSearchMessagesResult in
return ChatListSearchMessagesResult(query: query, messages: result.messages.sorted(by: { $0.index > $1.index }), readStates: result.readStates, hasMore: !result.completed, state: updatedState)
return ChatListSearchMessagesResult(query: finalQuery, messages: result.messages.sorted(by: { $0.index > $1.index }), readStates: result.readStates, hasMore: !result.completed, state: updatedState)
}
let loadMore = searchContext.get()
|> mapToSignal { searchContext -> Signal<(([Message], [PeerId: CombinedPeerReadState], Int32), Bool), NoError> in
if let searchContext = searchContext {
if let _ = searchContext.loadMoreIndex {
return searchMessages(account: context.account, location: location, query: query, state: searchContext.result.state, limit: 80)
return searchMessages(account: context.account, location: location, query: finalQuery, state: searchContext.result.state, limit: 80)
|> map { result, updatedState -> ChatListSearchMessagesResult in
return ChatListSearchMessagesResult(query: query, messages: result.messages.sorted(by: { $0.index > $1.index }), readStates: result.readStates, hasMore: !result.completed, state: updatedState)
return ChatListSearchMessagesResult(query: finalQuery, messages: result.messages.sorted(by: { $0.index > $1.index }), readStates: result.readStates, hasMore: !result.completed, state: updatedState)
}
|> mapToSignal { foundMessages -> Signal<(([Message], [PeerId: CombinedPeerReadState], Int32), Bool), NoError> in
updateSearchContext { previous in
@ -818,7 +841,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
}
let resolvedMessage = .single(nil)
|> then(context.sharedContext.resolveUrl(account: context.account, url: query)
|> then(context.sharedContext.resolveUrl(account: context.account, url: finalQuery)
|> mapToSignal { resolvedUrl -> Signal<Message?, NoError> in
if case let .channelMessage(peerId, messageId) = resolvedUrl {
return downloadMessage(postbox: context.account.postbox, network: context.account.network, messageId: messageId)
@ -904,7 +927,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
globalExpandType = .none
}
let lowercasedQuery = query.lowercased()
let lowercasedQuery = finalQuery.lowercased()
if presentationData.strings.DialogList_SavedMessages.lowercased().hasPrefix(lowercasedQuery) || "saved messages".hasPrefix(lowercasedQuery) {
if !existingPeerIds.contains(accountPeer.id), filteredPeer(accountPeer, accountPeer) {
existingPeerIds.insert(accountPeer.id)
@ -986,8 +1009,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
}
}
if addContact != nil && isViablePhoneNumber(query) {
entries.append(.addContact(query, presentationData.theme, presentationData.strings))
if addContact != nil && isViablePhoneNumber(finalQuery) {
entries.append(.addContact(finalQuery, presentationData.theme, presentationData.strings))
}
return (entries, isSearching)

View File

@ -96,8 +96,10 @@ public extension MessageTags {
static let unseenPersonalMessage = MessageTags(rawValue: 1 << 5)
static let liveLocation = MessageTags(rawValue: 1 << 6)
static let gif = MessageTags(rawValue: 1 << 7)
static let photo = MessageTags(rawValue: 1 << 8)
static let video = MessageTags(rawValue: 1 << 9)
static let all: MessageTags = [.photoOrVideo, .file, .music, .webPage, .voiceOrInstantVideo, .unseenPersonalMessage, .liveLocation, .gif]
static let all: MessageTags = [.photoOrVideo, .file, .music, .webPage, .voiceOrInstantVideo, .unseenPersonalMessage, .liveLocation, .gif, .photo, .video]
}
public extension GlobalMessageTags {

View File

@ -9,6 +9,10 @@ import SyncCore
func messageFilterForTagMask(_ tagMask: MessageTags) -> Api.MessagesFilter? {
if tagMask == .photoOrVideo {
return Api.MessagesFilter.inputMessagesFilterPhotoVideo
} else if tagMask == .photo {
return Api.MessagesFilter.inputMessagesFilterPhotos
} else if tagMask == .video {
return Api.MessagesFilter.inputMessagesFilterVideo
} else if tagMask == .file {
return Api.MessagesFilter.inputMessagesFilterDocument
} else if tagMask == .music {

View File

@ -192,20 +192,7 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q
}
}
let filter: Api.MessagesFilter
if let tags = tags {
if tags.contains(.file) {
filter = .inputMessagesFilterDocument
} else if tags.contains(.music) {
filter = .inputMessagesFilterMusic
} else if tags.contains(.webPage) {
filter = .inputMessagesFilterUrl
} else {
filter = .inputMessagesFilterEmpty
}
} else {
filter = .inputMessagesFilterEmpty
}
let filter: Api.MessagesFilter = tags.flatMap { messageFilterForTagMask($0) } ?? .inputMessagesFilterEmpty
remoteSearchResult = account.postbox.transaction { transaction -> (peer: Peer, additionalPeer: Peer?, from: Peer?)? in
guard let peer = transaction.getPeer(peerId) else {
return nil

View File

@ -30,6 +30,7 @@ public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute],
if let _ = attachment as? TelegramMediaImage {
if !isSecret {
tags.insert(.photoOrVideo)
tags.insert(.photo)
}
} else if let file = attachment as? TelegramMediaFile {
var refinedTag: MessageTags? = .file
@ -41,7 +42,7 @@ public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute],
refinedTag = .voiceOrInstantVideo
} else {
if !isSecret {
refinedTag = .photoOrVideo
refinedTag = [.photoOrVideo, .video]
} else {
refinedTag = nil
}