Search filters fixes

This commit is contained in:
Ilya Laktyushin 2020-09-28 16:39:24 +04:00
parent 9b87791908
commit a8f4663852
6 changed files with 100 additions and 71 deletions

View File

@ -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

View File

@ -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([]))

View File

@ -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)
}

View File

@ -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)

View File

@ -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))))
}
}
}

View File

@ -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 {