mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Search filters fixes
This commit is contained in:
parent
9b87791908
commit
a8f4663852
@ -1151,7 +1151,12 @@ final class ChatListControllerNode: ASDisplayNode {
|
||||
return nil
|
||||
}
|
||||
|
||||
let contentNode = ChatListSearchContainerNode(context: self.context, filter: [], groupId: self.groupId, openPeer: { [weak self] peer, dismissSearch in
|
||||
var filter: ChatListNodePeersFilter = []
|
||||
if false, case .group = self.groupId {
|
||||
filter.insert(.excludeRecent)
|
||||
}
|
||||
|
||||
let contentNode = ChatListSearchContainerNode(context: self.context, filter: filter, groupId: self.groupId, openPeer: { [weak self] peer, dismissSearch in
|
||||
self?.requestOpenPeerFromSearch?(peer, dismissSearch)
|
||||
}, openDisabledPeer: { _ in
|
||||
}, openRecentPeerOptions: { [weak self] peer in
|
||||
|
@ -39,7 +39,7 @@ private enum ChatListTokenId: Int32 {
|
||||
final class ChatListSearchInteraction {
|
||||
let openPeer: (Peer, Bool) -> Void
|
||||
let openDisabledPeer: (Peer) -> Void
|
||||
let openMessage: (Peer, MessageId) -> Void
|
||||
let openMessage: (Peer, MessageId, Bool) -> Void
|
||||
let openUrl: (String) -> Void
|
||||
let clearRecentSearch: () -> Void
|
||||
let addContact: (String) -> Void
|
||||
@ -52,7 +52,7 @@ final class ChatListSearchInteraction {
|
||||
let updateSuggestedPeers: ([Peer], ChatListSearchPaneKey) -> Void
|
||||
let getSelectedMessageIds: () -> Set<MessageId>?
|
||||
|
||||
init(openPeer: @escaping (Peer, Bool) -> Void, openDisabledPeer: @escaping (Peer) -> Void, openMessage: @escaping (Peer, MessageId) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (MessageId, Bool) -> Void, messageContextAction: @escaping ((Message, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), mediaMessageContextAction: @escaping ((Message, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, updateSuggestedPeers: @escaping ([Peer], ChatListSearchPaneKey) -> Void, getSelectedMessageIds: @escaping () -> Set<MessageId>?) {
|
||||
init(openPeer: @escaping (Peer, Bool) -> Void, openDisabledPeer: @escaping (Peer) -> Void, openMessage: @escaping (Peer, MessageId, Bool) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (MessageId, Bool) -> Void, messageContextAction: @escaping ((Message, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), mediaMessageContextAction: @escaping ((Message, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, updateSuggestedPeers: @escaping ([Peer], ChatListSearchPaneKey) -> Void, getSelectedMessageIds: @escaping () -> Set<MessageId>?) {
|
||||
self.openPeer = openPeer
|
||||
self.openDisabledPeer = openDisabledPeer
|
||||
self.openMessage = openMessage
|
||||
@ -102,7 +102,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
private let suggestedDates = Promise<[(Date, String?)]>([])
|
||||
private let suggestedDates = Promise<[(Date?, Date, String?)]>([])
|
||||
private let suggestedPeers = Promise<[Peer]>([])
|
||||
private var suggestedFilters: [ChatListSearchFilter]?
|
||||
private let suggestedFiltersDisposable = MetaDisposable()
|
||||
@ -149,8 +149,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
}
|
||||
}, openDisabledPeer: { peer in
|
||||
openDisabledPeer(peer)
|
||||
}, openMessage: { peer, messageId in
|
||||
originalOpenMessage(peer, messageId, true)
|
||||
}, openMessage: { peer, messageId, deactivateOnAction in
|
||||
originalOpenMessage(peer, messageId, deactivateOnAction)
|
||||
if peer.id.namespace != Namespaces.Peer.SecretChat {
|
||||
addAppLogEvent(postbox: context.account.postbox, type: "search_global_open_message", peerId: peer.id, data: .dictionary(["msg_id": .number(Double(messageId.id))]))
|
||||
}
|
||||
@ -269,7 +269,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
}
|
||||
|
||||
var key: ChatListSearchPaneKey?
|
||||
var maxDate = strongSelf.currentSearchOptions.maxDate
|
||||
var date = strongSelf.currentSearchOptions.date
|
||||
var peer = strongSelf.currentSearchOptions.peer
|
||||
|
||||
switch filter {
|
||||
@ -285,8 +285,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
key = .music
|
||||
case .voice:
|
||||
key = .voice
|
||||
case let .date(date, title):
|
||||
maxDate = (date, title)
|
||||
case let .date(minDate, maxDate, title):
|
||||
date = (minDate, maxDate, title)
|
||||
case let .peer(id, isGroup, _, compactDisplayTitle):
|
||||
peer = (id, isGroup, compactDisplayTitle)
|
||||
}
|
||||
@ -294,16 +294,28 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
if let key = key {
|
||||
strongSelf.paneContainerNode.requestSelectPane(key)
|
||||
} else {
|
||||
strongSelf.updateSearchOptions(strongSelf.currentSearchOptions.withUpdatedMaxDate(maxDate).withUpdatedPeer(peer), clearQuery: true)
|
||||
strongSelf.updateSearchOptions(strongSelf.currentSearchOptions.withUpdatedDate(date).withUpdatedPeer(peer), clearQuery: true)
|
||||
}
|
||||
}
|
||||
|
||||
self.suggestedFiltersDisposable.set((combineLatest(self.suggestedPeers.get(), self.suggestedDates.get(), self.selectedFilterKeyPromise.get())
|
||||
|> mapToSignal { peers, dates, selectedFilter -> Signal<([Peer], [(Date, String?)], ChatListSearchFilterEntryId?), NoError> in
|
||||
if (peers.isEmpty && dates.isEmpty) || peers.isEmpty {
|
||||
let suggestedPeers = self.searchQuery.get()
|
||||
|> mapToSignal { query -> Signal<[Peer], NoError> in
|
||||
if let query = query {
|
||||
return context.account.postbox.searchPeers(query: query.lowercased())
|
||||
|> map { local -> [Peer] in
|
||||
return Array(local.compactMap { $0.peer }.prefix(10))
|
||||
}
|
||||
} else {
|
||||
return .single([])
|
||||
}
|
||||
}
|
||||
|
||||
self.suggestedFiltersDisposable.set((combineLatest(suggestedPeers, self.suggestedDates.get(), self.selectedFilterKeyPromise.get(), self.searchQuery.get())
|
||||
|> mapToSignal { peers, dates, selectedFilter, searchQuery -> Signal<([Peer], [(Date?, Date, String?)], ChatListSearchFilterEntryId?), NoError> in
|
||||
if searchQuery?.isEmpty ?? true {
|
||||
return .single((peers, dates, selectedFilter))
|
||||
} else {
|
||||
return (.complete() |> delay(0.2, queue: Queue.mainQueue()))
|
||||
return (.complete() |> delay(0.25, queue: Queue.mainQueue()))
|
||||
|> then(.single((peers, dates, selectedFilter)))
|
||||
}
|
||||
} |> map { peers, dates, selectedFilter -> [ChatListSearchFilter] in
|
||||
@ -313,9 +325,9 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
formatter.timeStyle = .none
|
||||
formatter.dateStyle = .medium
|
||||
|
||||
for (date, string) in dates {
|
||||
let title = string ?? formatter.string(from: date)
|
||||
suggestedFilters.append(.date(Int32(date.timeIntervalSince1970), title))
|
||||
for (minDate, maxDate, string) in dates {
|
||||
let title = string ?? formatter.string(from: maxDate)
|
||||
suggestedFilters.append(.date(minDate.flatMap { Int32($0.timeIntervalSince1970) }, Int32(maxDate.timeIntervalSince1970), title))
|
||||
}
|
||||
}
|
||||
if !peers.isEmpty && selectedFilter != .filter(ChatListSearchFilter.chats.id) {
|
||||
@ -339,7 +351,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
}
|
||||
var filteredFilters: [ChatListSearchFilter] = []
|
||||
for filter in filters {
|
||||
if case .date = filter, strongSelf.searchOptionsValue?.maxDate == nil {
|
||||
if case .date = filter, strongSelf.searchOptionsValue?.date == nil {
|
||||
filteredFilters.append(filter)
|
||||
}
|
||||
if case .peer = filter, strongSelf.searchOptionsValue?.peer == nil {
|
||||
@ -390,7 +402,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
}
|
||||
|
||||
private var currentSearchOptions: ChatListSearchOptions {
|
||||
return self.searchOptionsValue ?? ChatListSearchOptions(peer: nil, minDate: nil, maxDate: nil)
|
||||
return self.searchOptionsValue ?? ChatListSearchOptions(peer: nil, date: nil)
|
||||
}
|
||||
|
||||
public override func searchTokensUpdated(tokens: [SearchBarToken]) {
|
||||
@ -399,8 +411,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
for token in tokens {
|
||||
tokensIdSet.insert(token.id)
|
||||
}
|
||||
if !tokensIdSet.contains(ChatListTokenId.date.rawValue) && updatedOptions?.maxDate != nil {
|
||||
updatedOptions = updatedOptions?.withUpdatedMaxDate(nil)
|
||||
if !tokensIdSet.contains(ChatListTokenId.date.rawValue) && updatedOptions?.date != nil {
|
||||
updatedOptions = updatedOptions?.withUpdatedDate(nil)
|
||||
}
|
||||
if !tokensIdSet.contains(ChatListTokenId.peer.rawValue) && updatedOptions?.peer != nil {
|
||||
updatedOptions = updatedOptions?.withUpdatedPeer(nil)
|
||||
@ -429,7 +441,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
tokens.append(SearchBarToken(id: ChatListTokenId.peer.rawValue, icon:image, title: peerName))
|
||||
}
|
||||
|
||||
if let (_, dateTitle) = options?.maxDate {
|
||||
if let (_, _, dateTitle) = options?.date {
|
||||
tokens.append(SearchBarToken(id: ChatListTokenId.date.rawValue, icon: UIImage(bundleImageName: "Chat List/Search/Calendar"), title: dateTitle))
|
||||
|
||||
self.suggestedDates.set(.single([]))
|
||||
|
@ -15,7 +15,7 @@ enum ChatListSearchFilter: Equatable {
|
||||
case music
|
||||
case voice
|
||||
case peer(PeerId, Bool, String, String)
|
||||
case date(Int32, String)
|
||||
case date(Int32?, Int32, String)
|
||||
|
||||
var id: Int32 {
|
||||
switch self {
|
||||
@ -33,7 +33,7 @@ enum ChatListSearchFilter: Equatable {
|
||||
return 5
|
||||
case let .peer(peerId, _, _, _):
|
||||
return peerId.id
|
||||
case let .date(date, _):
|
||||
case let .date(_, date, _):
|
||||
return date
|
||||
}
|
||||
}
|
||||
@ -139,7 +139,7 @@ private final class ItemNode: ASDisplayNode {
|
||||
image = UIImage(bundleImageName: "Chat List/Search/User")
|
||||
}
|
||||
icon = generateTintedImage(image: image, color: color)
|
||||
case let .date(_, displayTitle):
|
||||
case let .date(_, _, displayTitle):
|
||||
title = displayTitle
|
||||
icon = generateTintedImage(image: UIImage(bundleImageName: "Chat List/Search/Calendar"), color: color)
|
||||
}
|
||||
|
@ -615,23 +615,18 @@ public enum ChatListSearchContextActionSource {
|
||||
|
||||
public struct ChatListSearchOptions {
|
||||
let peer: (PeerId, Bool, String)?
|
||||
let minDate: (Int32, String)?
|
||||
let maxDate: (Int32, String)?
|
||||
let date: (Int32?, Int32, String)?
|
||||
|
||||
var isEmpty: Bool {
|
||||
return self.peer == nil && self.minDate == nil && self.maxDate == nil
|
||||
return self.peer == nil && self.date == nil
|
||||
}
|
||||
|
||||
func withUpdatedPeer(_ peerIdIsGroupAndName: (PeerId, Bool, String)?) -> ChatListSearchOptions {
|
||||
return ChatListSearchOptions(peer: peerIdIsGroupAndName, minDate: self.minDate, maxDate: self.maxDate)
|
||||
return ChatListSearchOptions(peer: peerIdIsGroupAndName, date: self.date)
|
||||
}
|
||||
|
||||
func withUpdatedMinDate(_ minDateAndTitle: (Int32, String)?) -> ChatListSearchOptions {
|
||||
return ChatListSearchOptions(peer: self.peer, minDate: minDateAndTitle, maxDate: self.maxDate)
|
||||
}
|
||||
|
||||
func withUpdatedMaxDate(_ maxDateAndTitle: (Int32, String)?) -> ChatListSearchOptions {
|
||||
return ChatListSearchOptions(peer: self.peer, minDate: self.minDate, maxDate: maxDateAndTitle)
|
||||
func withUpdatedDate(_ minDateMaxDateAndTitle: (Int32?, Int32, String)?) -> ChatListSearchOptions {
|
||||
return ChatListSearchOptions(peer: self.peer, date: minDateMaxDateAndTitle)
|
||||
}
|
||||
}
|
||||
|
||||
@ -880,12 +875,12 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
let location: SearchMessagesLocation
|
||||
if let options = options {
|
||||
if let (peerId, _, _) = options.peer {
|
||||
location = .peer(peerId: peerId, fromId: nil, tags: tagMask, topMsgId: nil, minDate: options.minDate?.0, maxDate: options.maxDate?.0)
|
||||
location = .peer(peerId: peerId, fromId: nil, tags: tagMask, topMsgId: nil, minDate: options.date?.0, maxDate: options.date?.1)
|
||||
} else {
|
||||
if let groupId = groupId {
|
||||
location = .group(groupId: groupId, tags: tagMask, minDate: options.minDate?.0, maxDate: options.maxDate?.0)
|
||||
location = .group(groupId: groupId, tags: tagMask, minDate: options.date?.0, maxDate: options.date?.1)
|
||||
} else {
|
||||
location = .general(tags: tagMask, minDate: options.minDate?.0, maxDate: options.maxDate?.0)
|
||||
location = .general(tags: tagMask, minDate: options.date?.0, maxDate: options.date?.1)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1208,8 +1203,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
}, additionalCategorySelected: { _ in
|
||||
}, messageSelected: { [weak self] peer, message, _ in
|
||||
interaction.dismissInput()
|
||||
if let peer = message.peers[message.id.peerId] {
|
||||
interaction.openMessage(peer, message.id)
|
||||
if let strongSelf = self, let peer = message.peers[message.id.peerId] {
|
||||
interaction.openMessage(peer, message.id, strongSelf.key == .chats)
|
||||
}
|
||||
self?.listNode.clearHighlightAnimated(true)
|
||||
}, groupSelected: { _ in
|
||||
@ -1336,7 +1331,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
}
|
||||
}
|
||||
|
||||
if strongSelf.tagMask != nil || strongSelf.searchOptionsValue?.maxDate != nil || strongSelf.searchOptionsValue?.peer != nil {
|
||||
if strongSelf.tagMask != nil || strongSelf.searchOptionsValue?.date != nil || strongSelf.searchOptionsValue?.peer != nil {
|
||||
entriesAndFlags?.0 = filteredEntries
|
||||
}
|
||||
}
|
||||
@ -2013,7 +2008,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
emptyResultsTitle = strongSelf.presentationData.strings.ChatList_Search_NoResults
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsQueryDescription(query).0
|
||||
} else {
|
||||
if let searchOptions = searchOptions, searchOptions.minDate == nil && searchOptions.maxDate == nil && searchOptions.peer == nil {
|
||||
if let searchOptions = searchOptions, searchOptions.date == nil && searchOptions.peer == nil {
|
||||
emptyResultsTitle = strongSelf.presentationData.strings.ChatList_Search_NoResultsFilter
|
||||
if strongSelf.tagMask == .photoOrVideo {
|
||||
emptyResultsText = strongSelf.presentationData.strings.ChatList_Search_NoResultsFitlerMedia
|
||||
@ -2047,7 +2042,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
strongSelf.emptyResultsTextNode.isHidden = !emptyResults
|
||||
strongSelf.emptyResultsAnimationNode.visibility = emptyResults
|
||||
|
||||
let displayPlaceholder = transition.isLoading && (strongSelf.key != .chats || strongSelf.searchOptionsValue?.peer != nil || strongSelf.searchOptionsValue?.minDate != nil || strongSelf.searchOptionsValue?.maxDate != nil)
|
||||
let displayPlaceholder = transition.isLoading && (strongSelf.key != .chats || strongSelf.searchOptionsValue?.peer != nil || strongSelf.searchOptionsValue?.date != nil)
|
||||
ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut).updateAlpha(node: strongSelf.shimmerNode, alpha: displayPlaceholder ? 1.0 : 0.0)
|
||||
|
||||
strongSelf.recentListNode.isHidden = displayingResults || strongSelf.peersFilter.contains(.excludeRecent)
|
||||
@ -2274,7 +2269,7 @@ private final class ChatListSearchShimmerNode: ASDisplayNode {
|
||||
return ListMessageItem(presentationData: ChatPresentationData(presentationData: presentationData), context: context, chatLocation: .peer(peer1.id), interaction: ListMessageItemInteraction.default, message: message, selection: .none, displayHeader: false, customHeader: nil, hintIsLink: true, isGlobalSearchResult: true)
|
||||
case .files:
|
||||
var media: [Media] = []
|
||||
media.append(TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: [.Audio(isVoice: false, duration: 0, title: nil, performer: nil, waveform: MemoryBuffer(data: Data()))]))
|
||||
media.append(TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: 0, attributes: [.FileName(fileName: "Text.txt")]))
|
||||
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer1, text: "Text", attributes: [], media: media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [])
|
||||
|
||||
return ListMessageItem(presentationData: ChatPresentationData(presentationData: presentationData), context: context, chatLocation: .peer(peer1.id), interaction: ListMessageItemInteraction.default, message: message, selection: .none, displayHeader: false, customHeader: nil, hintIsLink: false, isGlobalSearchResult: true)
|
||||
@ -2356,7 +2351,7 @@ private final class ChatListSearchShimmerNode: ASDisplayNode {
|
||||
fillLabelPlaceholderRect(origin: CGPoint(x: titleFrame.minX + 120.0 + 10.0, y: currentY + floor((itemHeight - fakeLabelPlaceholderHeight) / 2.0)), width: 60.0)
|
||||
|
||||
let dateFrame = itemNode.dateNode.frame.offsetBy(dx: 0.0, dy: currentY)
|
||||
fillLabelPlaceholderRect(origin: CGPoint(x: dateFrame.maxX - 30.0, y: dateFrame.minY), width: 30.0)
|
||||
fillLabelPlaceholderRect(origin: CGPoint(x: dateFrame.maxX - 30.0, y: floor(dateFrame.midY - fakeLabelPlaceholderHeight / 2.0)), width: 30.0)
|
||||
|
||||
context.setBlendMode(.normal)
|
||||
context.setFillColor(presentationData.theme.chatList.itemSeparatorColor.cgColor)
|
||||
@ -2381,7 +2376,7 @@ private final class ChatListSearchShimmerNode: ASDisplayNode {
|
||||
fillLabelPlaceholderRect(origin: CGPoint(x: descriptionFrame.minX, y: floor(descriptionFrame.midY - fakeLabelPlaceholderHeight / 2.0)), width: isVoice ? 60.0 : 240.0)
|
||||
|
||||
let dateFrame = itemNode.dateNode.frame.offsetBy(dx: 0.0, dy: currentY)
|
||||
fillLabelPlaceholderRect(origin: CGPoint(x: dateFrame.maxX - 30.0, y: dateFrame.minY), width: 30.0)
|
||||
fillLabelPlaceholderRect(origin: CGPoint(x: dateFrame.maxX - 30.0, y: floor(dateFrame.midY - fakeLabelPlaceholderHeight / 2.0)), width: 30.0)
|
||||
|
||||
context.setBlendMode(.normal)
|
||||
context.setFillColor(presentationData.theme.chatList.itemSeparatorColor.cgColor)
|
||||
@ -2401,7 +2396,7 @@ private final class ChatListSearchShimmerNode: ASDisplayNode {
|
||||
fillLabelPlaceholderRect(origin: CGPoint(x: authorFrame.minX, y: floor(authorFrame.midY - fakeLabelPlaceholderHeight / 2.0)), width: 60.0)
|
||||
|
||||
let dateFrame = itemNode.dateNode.frame.offsetBy(dx: 0.0, dy: currentY)
|
||||
fillLabelPlaceholderRect(origin: CGPoint(x: dateFrame.maxX - 30.0, y: dateFrame.minY), width: 30.0)
|
||||
fillLabelPlaceholderRect(origin: CGPoint(x: dateFrame.maxX - 30.0, y: floor(dateFrame.midY - fakeLabelPlaceholderHeight / 2.0)), width: 30.0)
|
||||
|
||||
context.setBlendMode(.normal)
|
||||
context.setFillColor(presentationData.theme.chatList.itemSeparatorColor.cgColor)
|
||||
|
@ -4,7 +4,7 @@ import TelegramStringFormatting
|
||||
|
||||
private let telegramReleaseDate = Date(timeIntervalSince1970: 1376438400.0)
|
||||
|
||||
func suggestDates(for string: String, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat) -> [(Date, String?)] {
|
||||
func suggestDates(for string: String, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat) -> [(minDate: Date?, maxDate: Date, string: String?)] {
|
||||
let string = string.folding(options: .diacriticInsensitive, locale: .current).trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
|
||||
if string.count < 3 {
|
||||
return []
|
||||
@ -39,9 +39,14 @@ func suggestDates(for string: String, strings: PresentationStrings, dateTimeForm
|
||||
let yesterday = strings.Weekday_Yesterday
|
||||
let dateSeparator = dateTimeFormat.dateSeparator
|
||||
|
||||
var result: [(Date, String?)] = []
|
||||
var result: [(Date?, Date, String?)] = []
|
||||
|
||||
let calendar = Calendar.current
|
||||
func getLowerDate(for date: Date) -> Date {
|
||||
let components = calendar.dateComponents(in: .current, from: date)
|
||||
let upperComponents = DateComponents(year: components.year, month: components.month, day: components.day, hour: 0, minute: 0, second: 0)
|
||||
return calendar.date(from: upperComponents)!
|
||||
}
|
||||
func getUpperDate(for date: Date) -> Date {
|
||||
let components = calendar.dateComponents(in: .current, from: date)
|
||||
let upperComponents = DateComponents(year: components.year, month: components.month, day: components.day, hour: 23, minute: 59, second: 59)
|
||||
@ -54,15 +59,23 @@ func suggestDates(for string: String, strings: PresentationStrings, dateTimeForm
|
||||
return []
|
||||
}
|
||||
|
||||
let midnight = calendar.startOfDay(for: now)
|
||||
let midnightDate = calendar.startOfDay(for: now)
|
||||
if today.lowercased().hasPrefix(string) {
|
||||
let todayDate = getUpperDate(for: midnight)
|
||||
result.append((todayDate, today))
|
||||
let todayDate = getUpperDate(for: midnightDate)
|
||||
result.append((midnightDate, todayDate, today))
|
||||
}
|
||||
if yesterday.lowercased().hasPrefix(string) {
|
||||
let yesterdayMidnight = calendar.date(byAdding: .day, value: -1, to: midnight)!
|
||||
let yesterdayMidnight = calendar.date(byAdding: .day, value: -1, to: midnightDate)!
|
||||
let yesterdayDate = getUpperDate(for: yesterdayMidnight)
|
||||
result.append((yesterdayDate, yesterday))
|
||||
result.append((yesterdayMidnight, yesterdayDate, yesterday))
|
||||
}
|
||||
|
||||
func getLowerMonthDate(month: Int, year: Int) -> Date {
|
||||
let monthComponents = DateComponents(year: year, month: month)
|
||||
let date = calendar.date(from: monthComponents)!
|
||||
let range = calendar.range(of: .day, in: .month, for: date)!
|
||||
let upperComponents = DateComponents(year: year, month: month, day: 1, hour: 0, minute: 0, second: 0)
|
||||
return calendar.date(from: upperComponents)!
|
||||
}
|
||||
|
||||
func getUpperMonthDate(month: Int, year: Int) -> Date {
|
||||
@ -77,9 +90,10 @@ func suggestDates(for string: String, strings: PresentationStrings, dateTimeForm
|
||||
let decimalRange = string.rangeOfCharacter(from: .decimalDigits)
|
||||
if decimalRange != nil {
|
||||
if string.count == 4, let value = Int(string), value <= year {
|
||||
let date = getUpperMonthDate(month: 12, year: value)
|
||||
if date > telegramReleaseDate {
|
||||
result.append((date, "\(value)"))
|
||||
let minDate = getLowerMonthDate(month: 1, year: value)
|
||||
let maxDate = getUpperMonthDate(month: 12, year: value)
|
||||
if maxDate > telegramReleaseDate {
|
||||
result.append((minDate, maxDate, "\(value)"))
|
||||
}
|
||||
} else {
|
||||
do {
|
||||
@ -95,11 +109,11 @@ func suggestDates(for string: String, strings: PresentationStrings, dateTimeForm
|
||||
if stringComponents.count < 3 {
|
||||
for i in 0..<5 {
|
||||
if let date = calendar.date(byAdding: .year, value: -i, to: resultDate) {
|
||||
result.append((date, nil))
|
||||
result.append((nil, date, nil))
|
||||
}
|
||||
}
|
||||
} else if resultDate < now {
|
||||
result.append((resultDate, nil))
|
||||
result.append((nil, resultDate, nil))
|
||||
}
|
||||
}
|
||||
let dd = try NSDataDetector(types: NSTextCheckingResult.CheckingType.date.rawValue)
|
||||
@ -121,13 +135,14 @@ func suggestDates(for string: String, strings: PresentationStrings, dateTimeForm
|
||||
var nextDateComponent = calendar.dateComponents([.hour, .minute, .second], from: now)
|
||||
nextDateComponent.weekday = day + calendar.firstWeekday
|
||||
if let date = calendar.nextDate(after: now, matching: nextDateComponent, matchingPolicy: .nextTime, direction: .backward) {
|
||||
let upperDate = getUpperDate(for: date)
|
||||
let lowerAnchorDate = getLowerDate(for: date)
|
||||
let upperAnchorDate = getUpperDate(for: date)
|
||||
for i in 0..<5 {
|
||||
if let date = calendar.date(byAdding: .hour, value: -24 * 7 * i, to: upperDate) {
|
||||
if calendar.isDate(date, equalTo: now, toGranularity: .weekOfYear) {
|
||||
result.append((date, value.0))
|
||||
if let lowerDate = calendar.date(byAdding: .hour, value: -24 * 7 * i, to: lowerAnchorDate), let upperDate = calendar.date(byAdding: .hour, value: -24 * 7 * i, to: upperAnchorDate) {
|
||||
if calendar.isDate(upperDate, equalTo: now, toGranularity: .weekOfYear) {
|
||||
result.append((lowerDate, upperDate, value.0))
|
||||
} else {
|
||||
result.append((date, nil))
|
||||
result.append((lowerDate, upperDate, nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -143,15 +158,17 @@ func suggestDates(for string: String, strings: PresentationStrings, dateTimeForm
|
||||
let shortMonthName = value.1.lowercased()
|
||||
if cleanString == shortMonthName || (cleanString.count >= shortMonthName.count && monthName.hasPrefix(cleanString)) {
|
||||
if cleanDigits.count == 4, let year = Int(cleanDigits) {
|
||||
let date = getUpperMonthDate(month: month, year: year)
|
||||
if date <= now && date > telegramReleaseDate {
|
||||
result.append((date, stringForMonth(strings: strings, month: Int32(month - 1), ofYear: Int32(year - 1900))))
|
||||
let lowerDate = getLowerMonthDate(month: month, year: year)
|
||||
let upperDate = getUpperMonthDate(month: month, year: year)
|
||||
if upperDate <= now && upperDate > telegramReleaseDate {
|
||||
result.append((lowerDate, upperDate, stringForMonth(strings: strings, month: Int32(month - 1), ofYear: Int32(year - 1900))))
|
||||
}
|
||||
} else if cleanDigits.isEmpty {
|
||||
for i in (year - 7 ... year).reversed() {
|
||||
let date = getUpperMonthDate(month: month, year: i)
|
||||
if date <= now && date > telegramReleaseDate {
|
||||
result.append((date, stringForMonth(strings: strings, month: Int32(month - 1), ofYear: Int32(i - 1900))))
|
||||
let lowerDate = getUpperMonthDate(month: month, year: i)
|
||||
let upperDate = getUpperMonthDate(month: month, year: i)
|
||||
if upperDate <= now && upperDate > telegramReleaseDate {
|
||||
result.append((lowerDate, upperDate, stringForMonth(strings: strings, month: Int32(month - 1), ofYear: Int32(i - 1900))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ final class ChatHistorySearchContainerNode: SearchDisplayControllerContentNode {
|
||||
transition.updateFrame(node: self.emptyResultsTextNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + padding + (layout.size.width - layout.safeInsets.left - layout.safeInsets.right - padding * 2.0 - emptyTextSize.width) / 2.0, y: emptyTitleY + emptyTitleSize.height + emptyTextSpacing), size: emptyTextSize))
|
||||
|
||||
self.listNode.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: layout.size, insets: UIEdgeInsets(top: topInset, left: 0.0, bottom: layout.intrinsicInsets.bottom, right: 0.0), duration: 0.0, curve: .Default(duration: nil)), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: layout.size, insets: UIEdgeInsets(top: topInset, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom, right: layout.safeInsets.right), duration: 0.0, curve: .Default(duration: nil)), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||
|
||||
|
||||
if firstValidLayout {
|
||||
|
Loading…
x
Reference in New Issue
Block a user