mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Search filters improvements
This commit is contained in:
parent
a05970c379
commit
a353608f4f
@ -5744,16 +5744,22 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"Call.AccountIsLoggedOnCurrentDevice" = "Sorry, you can't call %@ because that account is logged in to Telegram on the device you're using for the call.";
|
||||
|
||||
"ChatList.Search.FilterMedia" = "Media";
|
||||
"ChatList.Search.FilterPhotos" = "Photos";
|
||||
"ChatList.Search.FilterVideos" = "Video";
|
||||
"ChatList.Search.FilterLinks" = "Links";
|
||||
"ChatList.Search.FilterFiles" = "Files";
|
||||
"ChatList.Search.FilterMusic" = "Music";
|
||||
"ChatList.Search.FilterVoice" = "Voice";
|
||||
|
||||
"ChatList.Search.NoResults" = "No Results";
|
||||
"ChatList.Search.NoResultsQueryDescription" = "There were no results for \"%@\".\nTry a new search.";
|
||||
"ChatList.Search.NoResultsDescription" = "There were no results.\nTry a new search.";
|
||||
|
||||
"ChatList.Search.NoResultsFilter" = "Nothing Yet";
|
||||
"ChatList.Search.NoResultsFitlerMedia" = "Photos and videos from all your chats will be shown here.";
|
||||
"ChatList.Search.NoResultsFitlerLinks" = "Links from all your chats will be shown here.";
|
||||
"ChatList.Search.NoResultsFitlerFiles" = "Files from all your chats will be shown here.";
|
||||
"ChatList.Search.NoResultsFitlerMusic" = "Music from all your chats will be shown here.";
|
||||
"ChatList.Search.NoResultsFitlerVoice" = "Voice and video messages from all your chats will be shown here.";
|
||||
|
||||
"ChatList.Search.Messages_0" = "%@ messages";
|
||||
"ChatList.Search.Messages_1" = "%@ message";
|
||||
"ChatList.Search.Messages_2" = "%@ messages";
|
||||
@ -5761,34 +5767,6 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"ChatList.Search.Messages_many" = "%@ messages";
|
||||
"ChatList.Search.Messages_any" = "%@ messages";
|
||||
|
||||
"ChatList.Search.Photos_0" = "%@ photos";
|
||||
"ChatList.Search.Photos_1" = "%@ photo";
|
||||
"ChatList.Search.Photos_2" = "%@ photos";
|
||||
"ChatList.Search.Photos_3_10" = "%@ photos";
|
||||
"ChatList.Search.Photos_many" = "%@ photos";
|
||||
"ChatList.Search.Photos_any" = "%@ photos";
|
||||
|
||||
"ChatList.Search.Links_0" = "%@ links";
|
||||
"ChatList.Search.Links_1" = "%@ link";
|
||||
"ChatList.Search.Links_2" = "%@ links";
|
||||
"ChatList.Search.Links_3_10" = "%@ links";
|
||||
"ChatList.Search.Links_many" = "%@ links";
|
||||
"ChatList.Search.Links_any" = "%@ links";
|
||||
|
||||
"ChatList.Search.Files_0" = "%@ files";
|
||||
"ChatList.Search.Files_1" = "%@ file";
|
||||
"ChatList.Search.Files_2" = "%@ files";
|
||||
"ChatList.Search.Files_3_10" = "%@ files";
|
||||
"ChatList.Search.Files_many" = "%@ files";
|
||||
"ChatList.Search.Files_any" = "%@ files";
|
||||
|
||||
"ChatList.Search.Music_0" = "%@ audio files";
|
||||
"ChatList.Search.Music_1" = "%@ audio file";
|
||||
"ChatList.Search.Music_2" = "%@ audio files";
|
||||
"ChatList.Search.Music_3_10" = "%@ audio files";
|
||||
"ChatList.Search.Music_many" = "%@ audio files";
|
||||
"ChatList.Search.Music_any" = "%@ audio files";
|
||||
|
||||
"Conversation.InputTextAnonymousPlaceholder" = "Send anonymously";
|
||||
|
||||
"DialogList.Replies" = "Replies";
|
||||
|
@ -22,10 +22,6 @@ public enum ChatListSearchItemHeaderType {
|
||||
case chatTypes
|
||||
case faq
|
||||
case messages(Int32)
|
||||
case photos(Int32)
|
||||
case links(Int32)
|
||||
case files(Int32)
|
||||
case music(Int32)
|
||||
|
||||
fileprivate func title(strings: PresentationStrings) -> String {
|
||||
switch self {
|
||||
@ -63,14 +59,6 @@ public enum ChatListSearchItemHeaderType {
|
||||
return strings.Settings_FrequentlyAskedQuestions
|
||||
case let .messages(count):
|
||||
return strings.ChatList_Search_Messages(count)
|
||||
case let .photos(count):
|
||||
return strings.ChatList_Search_Photos(count)
|
||||
case let .links(count):
|
||||
return strings.ChatList_Search_Links(count)
|
||||
case let .files(count):
|
||||
return strings.ChatList_Search_Files(count)
|
||||
case let .music(count):
|
||||
return strings.ChatList_Search_Music(count)
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,14 +98,6 @@ public enum ChatListSearchItemHeaderType {
|
||||
return .faq
|
||||
case .messages:
|
||||
return .messages
|
||||
case .photos:
|
||||
return .photos
|
||||
case .links:
|
||||
return .links
|
||||
case .files:
|
||||
return .files
|
||||
case .music:
|
||||
return .music
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -464,11 +464,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
||||
gesture?.cancel()
|
||||
}
|
||||
}
|
||||
}, arrowAction: {
|
||||
if let chatPeer = chatPeer {
|
||||
searchPeer(chatPeer)
|
||||
}
|
||||
})
|
||||
}, arrowAction: nil)
|
||||
case let .globalPeer(peer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, expandType):
|
||||
var enabled = true
|
||||
if filter.contains(.onlyWriteable) {
|
||||
@ -529,37 +525,10 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
||||
}
|
||||
})
|
||||
case let .message(message, peer, readState, presentationData, totalCount, selected, displayCustomHeader):
|
||||
let header: ChatListSearchItemHeader?
|
||||
if false, enableHeaders && displayCustomHeader {
|
||||
let type: ChatListSearchItemHeaderType
|
||||
if let searchOptions = searchOptions {
|
||||
if searchOptions.messageTags == .photoOrVideo {
|
||||
type = .photos(totalCount)
|
||||
} else if searchOptions.messageTags == .webPage {
|
||||
type = .links(totalCount)
|
||||
} else if searchOptions.messageTags == .file {
|
||||
type = .files(totalCount)
|
||||
} else if searchOptions.messageTags == .music {
|
||||
type = .music(totalCount)
|
||||
} else {
|
||||
type = .messages(totalCount)
|
||||
}
|
||||
} else {
|
||||
type = .messages(totalCount)
|
||||
}
|
||||
header = ChatListSearchItemHeader(type: type, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil)
|
||||
} else {
|
||||
header = nil
|
||||
}
|
||||
|
||||
let selection: ChatHistoryMessageSelection
|
||||
if let selected = selected {
|
||||
selection = .selectable(selected: selected)
|
||||
} else {
|
||||
selection = .none
|
||||
}
|
||||
let header = ChatListSearchItemHeader(type: .messages(totalCount), theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil)
|
||||
let selection: ChatHistoryMessageSelection = selected.flatMap { .selectable(selected: $0) } ?? .none
|
||||
if let tags = searchOptions?.messageTags, tags != .photoOrVideo {
|
||||
return ListMessageItem(presentationData: ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: .builtin(WallpaperSettings())), fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: false, chatBubbleCorners: PresentationChatBubbleCorners(mainRadius: 0.0, auxiliaryRadius: 0.0, mergeBubbleCorners: false)), context: context, chatLocation: .peer(peer.peerId), interaction: listInteraction, message: message, selection: selection, displayHeader: enableHeaders && !displayCustomHeader, customHeader: displayCustomHeader ? header : nil, isGlobalSearchResult: true)
|
||||
return ListMessageItem(presentationData: ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: .builtin(WallpaperSettings())), fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations, largeEmoji: false, chatBubbleCorners: PresentationChatBubbleCorners(mainRadius: 0.0, auxiliaryRadius: 0.0, mergeBubbleCorners: false)), context: context, chatLocation: .peer(peer.peerId), interaction: listInteraction, message: message, selection: selection, displayHeader: enableHeaders && !displayCustomHeader, customHeader: nil, hintIsLink: tags == .webPage, isGlobalSearchResult: true)
|
||||
} else {
|
||||
return ChatListItem(presentationData: presentationData, context: context, peerGroupId: .root, filterData: nil, index: ChatListIndex(pinningIndex: nil, messageIndex: message.index), content: .peer(messages: [message], peer: peer, combinedReadState: readState, isRemovedFromTotalUnreadCount: false, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), embeddedState: nil, inputActivities: nil, promoInfo: nil, ignoreUnreadBadge: true, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: header, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||
}
|
||||
@ -1092,8 +1061,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
globalExpandType = .none
|
||||
}
|
||||
|
||||
if let _ = options?.messageTags, finalQuery.isEmpty {
|
||||
} else if let _ = options?.peerId {
|
||||
if options?.messageTags != nil || options?.maxDate != nil || options?.peerId != nil {
|
||||
} else {
|
||||
let lowercasedQuery = finalQuery.lowercased()
|
||||
if lowercasedQuery.count > 1 && presentationData.strings.DialogList_SavedMessages.lowercased().hasPrefix(lowercasedQuery) || "saved messages".hasPrefix(lowercasedQuery) {
|
||||
@ -1217,8 +1185,24 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
}
|
||||
}
|
||||
|
||||
let openUrlImpl: (String) -> Void = { url in
|
||||
openUserGeneratedUrl(context: context, url: url, concealed: false, present: { c in
|
||||
present(c, nil)
|
||||
}, openResolved: { [weak self] resolved in
|
||||
context.sharedContext.openResolvedUrl(resolved, context: context, urlContext: .generic, navigationController: navigationController, openPeer: { peerId, navigation in
|
||||
// self?.openPeer(peerId: peerId, navigation: navigation)
|
||||
}, sendFile: nil,
|
||||
sendSticker: nil,
|
||||
present: { c, a in
|
||||
present(c, a)
|
||||
}, dismissInput: {
|
||||
self?.dismissInput()
|
||||
}, contentContext: nil)
|
||||
})
|
||||
}
|
||||
|
||||
openMediaMessageImpl = { [weak self] message, mode in
|
||||
let _ = context.sharedContext.openChatMessage(OpenChatMessageParams(context: context, chatLocation: nil, chatLocationContextHolder: nil, message: message, standalone: false, reverseMessageGalleryOrder: true, navigationController: navigationController, dismissInput: {
|
||||
let _ = context.sharedContext.openChatMessage(OpenChatMessageParams(context: context, chatLocation: nil, chatLocationContextHolder: nil, message: message, standalone: false, reverseMessageGalleryOrder: true, mode: mode, navigationController: navigationController, dismissInput: {
|
||||
self?.dismissInput()
|
||||
}, present: { c, a in
|
||||
present(c, a)
|
||||
@ -1226,20 +1210,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
return transitionNodeImpl?(messageId, media)
|
||||
}, addToTransitionSurface: { view in
|
||||
addToTransitionSurfaceImpl?(view)
|
||||
}, openUrl: { [weak self] url in
|
||||
openUserGeneratedUrl(context: context, url: url, concealed: false, present: { c in
|
||||
present(c, nil)
|
||||
}, openResolved: { [weak self] resolved in
|
||||
context.sharedContext.openResolvedUrl(resolved, context: context, urlContext: .generic, navigationController: navigationController, openPeer: { peerId, navigation in
|
||||
// self?.openPeer(peerId: peerId, navigation: navigation)
|
||||
}, sendFile: nil,
|
||||
sendSticker: nil,
|
||||
present: { c, a in
|
||||
present(c, a)
|
||||
}, dismissInput: {
|
||||
self?.dismissInput()
|
||||
}, contentContext: nil)
|
||||
})
|
||||
}, openUrl: { url in
|
||||
openUrlImpl(url)
|
||||
}, openPeer: { peer, navigation in
|
||||
//self?.openPeer(peerId: peer.id, navigation: navigation)
|
||||
}, callPeer: { _, _ in
|
||||
@ -1459,40 +1431,35 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
|
||||
let listInteraction = ListMessageItemInteraction(openMessage: { [weak self] message, mode -> Bool in
|
||||
self?.dismissInput()
|
||||
let _ = (foundMessages
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { m in
|
||||
return context.sharedContext.openChatMessage(OpenChatMessageParams(context: context, chatLocation: nil, chatLocationContextHolder: nil, message: message, standalone: false, reverseMessageGalleryOrder: true, navigationController: navigationController, dismissInput: { [weak self] in
|
||||
self?.dismissInput()
|
||||
}, present: { c, a in
|
||||
present(c, a)
|
||||
}, transitionNode: { [weak self] messageId, media in
|
||||
var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||
if let strongSelf = self {
|
||||
strongSelf.listNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ListMessageNode {
|
||||
if let result = itemNode.transitionNode(id: messageId, media: media) {
|
||||
transitionNode = result
|
||||
}
|
||||
return context.sharedContext.openChatMessage(OpenChatMessageParams(context: context, chatLocation: nil, chatLocationContextHolder: nil, message: message, standalone: false, reverseMessageGalleryOrder: true, mode: mode, navigationController: navigationController, dismissInput: { [weak self] in
|
||||
self?.dismissInput()
|
||||
}, present: { c, a in
|
||||
present(c, a)
|
||||
}, transitionNode: { [weak self] messageId, media in
|
||||
var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||
if let strongSelf = self {
|
||||
strongSelf.listNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ListMessageNode {
|
||||
if let result = itemNode.transitionNode(id: messageId, media: media) {
|
||||
transitionNode = result
|
||||
}
|
||||
}
|
||||
}
|
||||
return transitionNode
|
||||
}, addToTransitionSurface: { view in
|
||||
self?.view.addSubview(view)
|
||||
}, openUrl: { url in
|
||||
// self?.openUrl(url: url, concealed: false, external: false)
|
||||
}, openPeer: { peer, navigation in
|
||||
// self?.openPeer(peerId: peer.id, navigation: navigation)
|
||||
}, callPeer: { _, _ in
|
||||
}, enqueueMessage: { _ in
|
||||
}, sendSticker: nil, setupTemporaryHiddenMedia: { _, _, _ in }, chatAvatarHiddenMedia: { _, _ in }, playlistLocation: .custom(messages: foundMessages, at: message.id, loadMore: {
|
||||
loadMore()
|
||||
}), gallerySource: .custom(messages: foundMessages, messageId: message.id, loadMore: {
|
||||
loadMore()
|
||||
})))
|
||||
})
|
||||
return true
|
||||
}
|
||||
return transitionNode
|
||||
}, addToTransitionSurface: { view in
|
||||
self?.view.addSubview(view)
|
||||
}, openUrl: { url in
|
||||
openUrlImpl(url)
|
||||
}, openPeer: { peer, navigation in
|
||||
// self?.openPeer(peerId: peer.id, navigation: navigation)
|
||||
}, callPeer: { _, _ in
|
||||
}, enqueueMessage: { _ in
|
||||
}, sendSticker: nil, setupTemporaryHiddenMedia: { _, _, _ in }, chatAvatarHiddenMedia: { _, _ in }, playlistLocation: .custom(messages: foundMessages, at: message.id, loadMore: {
|
||||
loadMore()
|
||||
}), gallerySource: .custom(messages: foundMessages, messageId: message.id, loadMore: {
|
||||
loadMore()
|
||||
})))
|
||||
}, openMessageContextMenu: { [weak self] message, bool, node, rect, gesture in
|
||||
self?.messageContextAction(message, node: node, rect: rect, gesture: gesture)
|
||||
}, toggleMessagesSelection: { messageId, selected in
|
||||
@ -1500,19 +1467,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
toggleMessageSelectionImpl?(messageId, selected)
|
||||
}
|
||||
}, openUrl: { url, _, _, message in
|
||||
openUserGeneratedUrl(context: context, url: url, concealed: false, present: { c in
|
||||
present(c, nil)
|
||||
}, openResolved: { [weak self] resolved in
|
||||
context.sharedContext.openResolvedUrl(resolved, context: context, urlContext: .generic, navigationController: navigationController, openPeer: { peerId, navigation in
|
||||
// self?.openPeer(peerId: peerId, navigation: navigation)
|
||||
}, sendFile: nil,
|
||||
sendSticker: nil,
|
||||
present: { c, a in
|
||||
present(c, a)
|
||||
}, dismissInput: {
|
||||
self?.dismissInput()
|
||||
}, contentContext: nil)
|
||||
})
|
||||
openUrlImpl(url)
|
||||
}, openInstantPage: { message, data in
|
||||
if let (webpage, anchor) = instantPageAndAnchor(message: message) {
|
||||
let pageController = InstantPageController(context: context, webPage: webpage, sourcePeerType: .channel, anchor: anchor)
|
||||
@ -1631,8 +1586,10 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let messageTags: MessageTags?
|
||||
var messageTags: MessageTags? = strongSelf.currentSearchOptions.messageTags
|
||||
var maxDate: Int32? = strongSelf.currentSearchOptions.maxDate
|
||||
var peerId: PeerId? = strongSelf.currentSearchOptions.peerId
|
||||
var peerName: String? = strongSelf.currentSearchOptions.peerName
|
||||
var clearQuery: Bool = false
|
||||
switch filter {
|
||||
case .media:
|
||||
@ -1646,11 +1603,14 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
case .voice:
|
||||
messageTags = .voiceOrInstantVideo
|
||||
case let .date(date, _):
|
||||
messageTags = strongSelf.currentSearchOptions.messageTags
|
||||
maxDate = date
|
||||
clearQuery = true
|
||||
case let .peer(id, name):
|
||||
peerId = id
|
||||
peerName = name
|
||||
clearQuery = true
|
||||
}
|
||||
strongSelf.updateSearchOptions(strongSelf.currentSearchOptions.withUpdatedMessageTags(messageTags).withUpdatedMaxDate(maxDate), clearQuery: clearQuery)
|
||||
strongSelf.updateSearchOptions(strongSelf.currentSearchOptions.withUpdatedMessageTags(messageTags).withUpdatedMaxDate(maxDate).withUpdatedPeerId(peerId, peerName: peerName), clearQuery: clearQuery)
|
||||
}
|
||||
|
||||
self.mediaStatusDisposable = (combineLatest(context.sharedContext.mediaManager.globalMediaPlayerState, self.searchOptions.get())
|
||||
@ -1661,6 +1621,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
if let playlistId = state.playlistId as? PeerMessagesMediaPlaylistId, case .custom = playlistId {
|
||||
if case .music = type, searchOptions?.messageTags == .music {
|
||||
return .single((account, state, type))
|
||||
} else if case .voice = type, searchOptions?.messageTags == .voiceOrInstantVideo {
|
||||
return .single((account, state, type))
|
||||
} else {
|
||||
return .single(nil) |> delay(0.1, queue: .mainQueue())
|
||||
}
|
||||
@ -1789,14 +1751,6 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
self.setQuery?(nil, tokens, self.searchQueryValue ?? "")
|
||||
}
|
||||
|
||||
if options?.peerId == nil {
|
||||
self.updateSearchState { state in
|
||||
var state = state
|
||||
state.expandLocalSearch = false
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
self.updatedSearchOptions?(options, self.possibleDate != nil)
|
||||
}
|
||||
|
||||
@ -1920,19 +1874,42 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
let displayingResults = transition.displayingResults
|
||||
self.listNode.transaction(deleteIndices: transition.deletions, insertIndicesAndItems: transition.insertions, updateIndicesAndItems: transition.updates, options: options, updateSizeAndInsets: nil, updateOpaqueState: nil, completion: { [weak self] _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.listNode.isHidden = strongSelf.searchOptionsValue?.messageTags == .photoOrVideo && (strongSelf.searchQueryValue ?? "").isEmpty
|
||||
let searchOptions = strongSelf.searchOptionsValue
|
||||
strongSelf.listNode.isHidden = searchOptions?.messageTags == .photoOrVideo && (strongSelf.searchQueryValue ?? "").isEmpty
|
||||
strongSelf.mediaNode.isHidden = !strongSelf.listNode.isHidden
|
||||
if !displayingResults {
|
||||
strongSelf.listNode.isHidden = true
|
||||
strongSelf.mediaNode.isHidden = true
|
||||
}
|
||||
|
||||
let emptyResultsTitle: String
|
||||
let emptyResultsText: String
|
||||
if transition.query.isEmpty {
|
||||
if !transition.query.isEmpty {
|
||||
emptyResultsTitle = strongSelf.presentationData.strings.ChatList_Search_NoResults
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsQueryDescription(transition.query).0
|
||||
} else {
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsDescription
|
||||
if let searchOptions = searchOptions, searchOptions.messageTags != nil && searchOptions.minDate == nil && searchOptions.maxDate == nil && searchOptions.peerId == nil {
|
||||
emptyResultsTitle = strongSelf.presentationData.strings.ChatList_Search_NoResultsFilter
|
||||
if searchOptions.messageTags == .photoOrVideo {
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsFitlerMedia
|
||||
} else if searchOptions.messageTags == .webPage {
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsFitlerLinks
|
||||
} else if searchOptions.messageTags == .file {
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsFitlerFiles
|
||||
} else if searchOptions.messageTags == .music {
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsFitlerMusic
|
||||
} else if searchOptions.messageTags == .voiceOrInstantVideo {
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsFitlerVoice
|
||||
} else {
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsDescription
|
||||
}
|
||||
} else {
|
||||
emptyResultsTitle = strongSelf.presentationData.strings.ChatList_Search_NoResults
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsDescription
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.emptyResultsTitleNode.attributedText = NSAttributedString(string: emptyResultsTitle, font: Font.semibold(17.0), textColor: strongSelf.presentationData.theme.list.freeTextColor)
|
||||
strongSelf.emptyResultsTextNode.attributedText = NSAttributedString(string: emptyResultsText, font: Font.regular(15.0), textColor: strongSelf.presentationData.theme.list.freeTextColor)
|
||||
|
||||
let emptyResults = displayingResults && transition.isEmpty
|
||||
@ -2085,6 +2062,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
let progressDisposable = MetaDisposable()
|
||||
var progressStarted = false
|
||||
strongSelf.playlistPreloadDisposable?.dispose()
|
||||
|
||||
|
||||
strongSelf.playlistPreloadDisposable = (signal
|
||||
|> afterDisposed {
|
||||
Queue.mainQueue().async {
|
||||
|
@ -13,6 +13,7 @@ enum ChatListSearchFilter: Equatable {
|
||||
case files
|
||||
case music
|
||||
case voice
|
||||
case peer(PeerId, String)
|
||||
case date(Int32, String)
|
||||
|
||||
var id: Int32 {
|
||||
@ -27,6 +28,8 @@ enum ChatListSearchFilter: Equatable {
|
||||
return 3
|
||||
case .voice:
|
||||
return 4
|
||||
case .peer:
|
||||
return 5
|
||||
case let .date(date, _):
|
||||
return date
|
||||
}
|
||||
@ -113,8 +116,11 @@ private final class ItemNode: ASDisplayNode {
|
||||
case .voice:
|
||||
title = presentationData.strings.ChatList_Search_FilterVoice
|
||||
icon = generateTintedImage(image: UIImage(bundleImageName: "Chat List/Search/Voice"), color: color)
|
||||
case let .date(_, dateTitle):
|
||||
title = dateTitle
|
||||
case let .peer(_, displayTitle):
|
||||
title = displayTitle
|
||||
icon = generateTintedImage(image: UIImage(bundleImageName: "Chat List/Search/User"), color: color)
|
||||
case let .date(_, displayTitle):
|
||||
title = displayTitle
|
||||
icon = generateTintedImage(image: UIImage(bundleImageName: "Chat List/Search/Calendar"), color: color)
|
||||
}
|
||||
|
||||
@ -252,7 +258,7 @@ final class ChatListSearchFiltersContainerNode: ASDisplayNode {
|
||||
totalRawTabSize += paneNodeSize.width
|
||||
}
|
||||
|
||||
let minSpacing: CGFloat = 26.0
|
||||
let minSpacing: CGFloat = 24.0
|
||||
var spacing = minSpacing
|
||||
|
||||
let resolvedSideInset: CGFloat = 16.0 + sideInset
|
||||
@ -270,10 +276,6 @@ final class ChatListSearchFiltersContainerNode: ASDisplayNode {
|
||||
}
|
||||
longTitlesWidth += resolvedSideInset
|
||||
|
||||
if longTitlesWidth < size.width && tabSizes.count > 3 {
|
||||
spacing = (size.width - titlesWidth - resolvedSideInset * 2.0) / CGFloat(tabSizes.count - 1)
|
||||
}
|
||||
|
||||
let verticalOffset: CGFloat = -3.0
|
||||
for i in 0 ..< tabSizes.count {
|
||||
let (_, paneNodeSize, paneNode, wasAdded) = tabSizes[i]
|
||||
|
@ -12,7 +12,6 @@ import RadialStatusNode
|
||||
import TelegramStringFormatting
|
||||
import UniversalMediaPlayer
|
||||
import ListMessageItem
|
||||
import ListSectionHeaderNode
|
||||
import ChatMessageInteractiveMediaBadge
|
||||
import ShimmerEffect
|
||||
import GridMessageSelectionNode
|
||||
@ -645,7 +644,6 @@ final class ChatListSearchMediaNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
private let contentType: ContentType
|
||||
|
||||
private let scrollNode: ASScrollNode
|
||||
private var headerNode: ListSectionHeaderNode
|
||||
private let floatingHeaderNode: FloatingHeaderNode
|
||||
private var flashHeaderDelayTimer: Foundation.Timer?
|
||||
private var isDeceleratingAfterTracking = false
|
||||
@ -686,9 +684,7 @@ final class ChatListSearchMediaNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
self.scrollNode = ASScrollNode()
|
||||
self.floatingHeaderNode = FloatingHeaderNode()
|
||||
self.floatingHeaderNode.alpha = 0.0
|
||||
|
||||
self.headerNode = ListSectionHeaderNode(theme: context.sharedContext.currentPresentationData.with { $0 }.theme)
|
||||
|
||||
|
||||
super.init()
|
||||
|
||||
self._itemInteraction = VisualMediaItemInteraction(
|
||||
@ -765,14 +761,7 @@ final class ChatListSearchMediaNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
self.initialized = true
|
||||
|
||||
if let (size, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData) = self.currentParams {
|
||||
if loading {
|
||||
self.headerNode.title = ""
|
||||
} else if totalCount > 0 {
|
||||
self.headerNode.title = presentationData.strings.ChatList_Search_Photos(totalCount).uppercased()
|
||||
}
|
||||
|
||||
self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expandProgress, presentationData: presentationData, synchronous: true, transition: .immediate)
|
||||
self.headerNode.alpha = self.mediaItems.isEmpty && !loading ? 0.0 : 1.0
|
||||
if !self.didSetReady {
|
||||
self.didSetReady = true
|
||||
self.ready.set(.single(true))
|
||||
@ -841,10 +830,8 @@ final class ChatListSearchMediaNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
func update(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
self.currentParams = (size, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
|
||||
let headerSize = CGSize(width: size.width, height: 0.0)
|
||||
|
||||
transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(x: 0.0, y: headerSize.height), size: CGSize(width: size.width, height: size.height - headerSize.height)))
|
||||
|
||||
transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height)))
|
||||
|
||||
let availableWidth = size.width - sideInset * 2.0
|
||||
|
||||
|
@ -458,11 +458,26 @@ public final class ListMessageFileItemNode: ListMessageNode {
|
||||
}
|
||||
titleText = NSAttributedString(string: authorName, font: audioTitleFont, textColor: item.presentationData.theme.theme.list.itemPrimaryTextColor)
|
||||
let dateString = stringForFullDate(timestamp: item.message.timestamp, strings: item.presentationData.strings, dateTimeFormat: item.presentationData.dateTimeFormat)
|
||||
let descriptionString: String
|
||||
var descriptionString: String = ""
|
||||
if let duration = file.duration {
|
||||
descriptionString = "\(stringForDuration(Int32(duration))) • \(dateString)"
|
||||
if item.isGlobalSearchResult {
|
||||
descriptionString = stringForDuration(Int32(duration))
|
||||
} else {
|
||||
descriptionString = "\(stringForDuration(Int32(duration))) • \(dateString)"
|
||||
}
|
||||
} else {
|
||||
descriptionString = dateString
|
||||
if !item.isGlobalSearchResult {
|
||||
descriptionString = dateString
|
||||
}
|
||||
}
|
||||
|
||||
if item.isGlobalSearchResult {
|
||||
let authorString = fullAuthorString(for: item)
|
||||
if descriptionString.isEmpty {
|
||||
descriptionString = authorString
|
||||
} else {
|
||||
descriptionString = "\(descriptionString) • \(authorString)"
|
||||
}
|
||||
}
|
||||
|
||||
descriptionText = NSAttributedString(string: descriptionString, font: descriptionFont, textColor: item.presentationData.theme.theme.list.itemSecondaryTextColor)
|
||||
|
@ -312,6 +312,21 @@ public final class ListMessageSnippetItemNode: ListMessageNode {
|
||||
}
|
||||
}
|
||||
|
||||
for media in item.message.media {
|
||||
if let image = media as? TelegramMediaImage {
|
||||
if let representation = imageRepresentationLargerThan(image.representations, size: PixelDimensions(width: 80, height: 80)) {
|
||||
iconImageReferenceAndRepresentation = (.message(message: MessageReference(item.message), media: image), representation)
|
||||
}
|
||||
break
|
||||
}
|
||||
if let file = media as? TelegramMediaFile {
|
||||
if let representation = smallestImageRepresentation(file.previewRepresentations) {
|
||||
iconImageReferenceAndRepresentation = (.message(message: MessageReference(item.message), media: file), representation)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var entities: [MessageTextEntity]?
|
||||
|
||||
entities = messageEntities
|
||||
@ -680,9 +695,7 @@ public final class ListMessageSnippetItemNode: ListMessageNode {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if !item.interaction.openMessage(item.message, .default) {
|
||||
item.interaction.openUrl(currentPrimaryUrl, false, false, nil)
|
||||
}
|
||||
item.interaction.openUrl(currentPrimaryUrl, false, false, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -133,7 +133,9 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
||||
control = .seek(time)
|
||||
}
|
||||
if (file.isVoice || file.isInstantVideo) && params.message.tags.contains(.voiceOrInstantVideo) {
|
||||
if params.standalone {
|
||||
if let playlistLocation = params.playlistLocation {
|
||||
location = playlistLocation
|
||||
} else if params.standalone {
|
||||
location = .recentActions(params.message)
|
||||
} else {
|
||||
location = .messages(peerId: params.message.id.peerId, tagMask: .voiceOrInstantVideo, at: params.message.id)
|
||||
|
@ -345,10 +345,6 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist {
|
||||
self.network = network
|
||||
self.messagesLocation = location
|
||||
|
||||
if case .custom = location {
|
||||
self.order = .reversed
|
||||
}
|
||||
|
||||
switch self.messagesLocation {
|
||||
case let .messages(_, _, messageId), let .singleMessage(messageId), let .custom(_, messageId, _):
|
||||
self.loadItem(anchor: .messageId(messageId), navigation: .later)
|
||||
@ -679,12 +675,13 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist {
|
||||
inputIndex = .single(index)
|
||||
case .random:
|
||||
var playbackStack = self.playbackStack
|
||||
inputIndex = self.postbox.transaction { transaction -> MessageIndex in
|
||||
inputIndex = messages
|
||||
|> map { messages, _, _ -> MessageIndex in
|
||||
if case let .random(previous) = navigation, previous {
|
||||
let _ = playbackStack.pop()
|
||||
while true {
|
||||
if let id = playbackStack.pop() {
|
||||
if let message = transaction.getMessage(id) {
|
||||
if let message = messages.first(where: { $0.id == id }) {
|
||||
return message.index
|
||||
}
|
||||
} else {
|
||||
@ -692,9 +689,8 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist {
|
||||
}
|
||||
}
|
||||
}
|
||||
return index
|
||||
// return transaction.findRandomMessage(peerId: peerId, namespace: Namespaces.Message.Cloud, tag: tagMask, ignoreIds: (playbackStack.ids, playbackStack.set)) ?? index
|
||||
}
|
||||
return messages.randomElement()?.index ?? index
|
||||
}
|
||||
}
|
||||
let historySignal = inputIndex
|
||||
|> mapToSignal { inputIndex -> Signal<(Message, [Message])?, NoError> in
|
||||
|
Loading…
x
Reference in New Issue
Block a user